Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions tests/disas/winch/x64/atomic/rmw/i32_atomic_rmw16_subu.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory 1 1 shared)
(func (export "_start") (result i32)
(i32.atomic.rmw16.sub_u (i32.const 0) (i32.const 42))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x64
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movl $0x2a, %eax
;; movl $0, %ecx
;; andw $1, %cx
;; cmpw $0, %cx
;; jne 0x66
;; 44: movl $0, %ecx
;; movq 0x58(%r14), %r11
;; movq (%r11), %rdx
;; addq %rcx, %rdx
;; negw %ax
;; lock xaddw %ax, (%rdx)
;; movzwl %ax, %eax
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 64: ud2
;; 66: ud2
31 changes: 31 additions & 0 deletions tests/disas/winch/x64/atomic/rmw/i32_atomic_rmw8_subu.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory 1 1 shared)
(func (export "_start") (result i32)
(i32.atomic.rmw8.sub_u (i32.const 0) (i32.const 42))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x4f
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movl $0x2a, %eax
;; movl $0, %ecx
;; movq 0x58(%r14), %r11
;; movq (%r11), %rdx
;; addq %rcx, %rdx
;; negb %al
;; lock xaddb %al, (%rdx)
;; movzbl %al, %eax
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 4f: ud2
35 changes: 35 additions & 0 deletions tests/disas/winch/x64/atomic/rmw/i32_atomic_rmw_sub.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory 1 1 shared)
(func (export "_start") (result i32)
(i32.atomic.rmw.sub (i32.const 0) (i32.const 42))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x5d
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movl $0x2a, %eax
;; movl $0, %ecx
;; andl $3, %ecx
;; cmpl $0, %ecx
;; jne 0x5f
;; 42: movl $0, %ecx
;; movq 0x58(%r14), %r11
;; movq (%r11), %rdx
;; addq %rcx, %rdx
;; negl %eax
;; lock xaddl %eax, (%rdx)
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 5d: ud2
;; 5f: ud2
36 changes: 36 additions & 0 deletions tests/disas/winch/x64/atomic/rmw/i64_atomic_rmw16_subu.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory 1 1 shared)
(func (export "_start") (result i64)
(i64.atomic.rmw16.sub_u (i32.const 0) (i64.const 42))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x67
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movq $0x2a, %rax
;; movl $0, %ecx
;; andw $1, %cx
;; cmpw $0, %cx
;; jne 0x69
;; 46: movl $0, %ecx
;; movq 0x58(%r14), %r11
;; movq (%r11), %rdx
;; addq %rcx, %rdx
;; negw %ax
;; lock xaddw %ax, (%rdx)
;; movzwq %ax, %rax
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 67: ud2
;; 69: ud2
36 changes: 36 additions & 0 deletions tests/disas/winch/x64/atomic/rmw/i64_atomic_rmw32_subu.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory 1 1 shared)
(func (export "_start") (result i64)
(i64.atomic.rmw32.sub_u (i32.const 0) (i64.const 42))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x61
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movq $0x2a, %rax
;; movl $0, %ecx
;; andl $3, %ecx
;; cmpl $0, %ecx
;; jne 0x63
;; 44: movl $0, %ecx
;; movq 0x58(%r14), %r11
;; movq (%r11), %rdx
;; addq %rcx, %rdx
;; negl %eax
;; lock xaddl %eax, (%rdx)
;; movl %eax, %eax
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 61: ud2
;; 63: ud2
31 changes: 31 additions & 0 deletions tests/disas/winch/x64/atomic/rmw/i64_atomic_rmw8_subu.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory 1 1 shared)
(func (export "_start") (result i64)
(i64.atomic.rmw8.sub_u (i32.const 0) (i64.const 42))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x52
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movq $0x2a, %rax
;; movl $0, %ecx
;; movq 0x58(%r14), %r11
;; movq (%r11), %rdx
;; addq %rcx, %rdx
;; negb %al
;; lock xaddb %al, (%rdx)
;; movzbq %al, %rax
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 52: ud2
35 changes: 35 additions & 0 deletions tests/disas/winch/x64/atomic/rmw/i64_atomic_rmw_sub.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
;;! target = "x86_64"
;;! test = "winch"

(module
(memory 1 1 shared)
(func (export "_start") (result i64)
(i64.atomic.rmw.sub (i32.const 0) (i64.const 42))))
;; wasm[0]::function[0]:
;; pushq %rbp
;; movq %rsp, %rbp
;; movq 8(%rdi), %r11
;; movq 0x10(%r11), %r11
;; addq $0x10, %r11
;; cmpq %rsp, %r11
;; ja 0x63
;; 1c: movq %rdi, %r14
;; subq $0x10, %rsp
;; movq %rdi, 8(%rsp)
;; movq %rsi, (%rsp)
;; movq $0x2a, %rax
;; movl $0, %ecx
;; andq $7, %rcx
;; cmpq $0, %rcx
;; jne 0x65
;; 46: movl $0, %ecx
;; movq 0x58(%r14), %r11
;; movq (%r11), %rdx
;; addq %rcx, %rdx
;; negq %rax
;; lock xaddq %rax, (%rdx)
;; addq $0x10, %rsp
;; popq %rbp
;; retq
;; 63: ud2
;; 65: ud2
17 changes: 9 additions & 8 deletions winch/codegen/src/isa/x64/masm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1329,15 +1329,16 @@ impl Masm for MacroAssembler {
RmwOp::Add => {
self.asm
.lock_xadd(addr, operand.to_reg(), operand, size, flags);
match extend {
// It is only necessary to zero-extend when the operand is less than 32bits.
// x64 automatically zero-extend 32bits to 64bit.
Some(extend) => {
self.asm.movzx_rr(operand.to_reg(), operand, extend);
}
_ => (),
}
}
RmwOp::Sub => {
self.asm.neg(operand.to_reg(), operand, size);
self.asm
.lock_xadd(addr, operand.to_reg(), operand, size, flags);
}
}

if let Some(extend) = extend {
self.asm.movzx_rr(operand.to_reg(), operand, extend);
}
Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions winch/codegen/src/masm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub(crate) enum MulWideKind {
/// Type of operation for a read-modify-write instruction.
pub(crate) enum RmwOp {
Add,
Sub,
}

/// The direction to perform the memory move.
Expand Down
67 changes: 66 additions & 1 deletion winch/codegen/src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,13 @@ macro_rules! def_unsupported {
(emit I64AtomicRmw32AddU $($rest:tt)*) => {};
(emit I64AtomicRmwAdd $($rest:tt)*) => {};
(emit I8x16Shuffle $($rest:tt)*) => {};
(emit I32AtomicRmw8SubU $($rest:tt)*) => {};
(emit I32AtomicRmw16SubU $($rest:tt)*) => {};
(emit I32AtomicRmwSub $($rest:tt)*) => {};
(emit I64AtomicRmw8SubU $($rest:tt)*) => {};
(emit I64AtomicRmw16SubU $($rest:tt)*) => {};
(emit I64AtomicRmw32SubU $($rest:tt)*) => {};
(emit I64AtomicRmwSub $($rest:tt)*) => {};

(emit $unsupported:tt $($rest:tt)*) => {$($rest)*};
}
Expand Down Expand Up @@ -2349,13 +2356,71 @@ where
}

fn visit_i64_atomic_rmw32_add_u(&mut self, arg: MemArg) -> Self::Output {
self.emit_atomic_rmw(&arg, RmwOp::Add, OperandSize::S32, None)
self.emit_atomic_rmw(
&arg,
RmwOp::Add,
OperandSize::S32,
Some(ExtendKind::I64Extend32U),
)
}

fn visit_i64_atomic_rmw_add(&mut self, arg: MemArg) -> Self::Output {
self.emit_atomic_rmw(&arg, RmwOp::Add, OperandSize::S64, None)
}

fn visit_i32_atomic_rmw_sub(&mut self, arg: MemArg) -> Self::Output {
self.emit_atomic_rmw(&arg, RmwOp::Sub, OperandSize::S32, None)
}

fn visit_i64_atomic_rmw_sub(&mut self, arg: MemArg) -> Self::Output {
self.emit_atomic_rmw(&arg, RmwOp::Sub, OperandSize::S64, None)
}

fn visit_i32_atomic_rmw8_sub_u(&mut self, arg: MemArg) -> Self::Output {
self.emit_atomic_rmw(
&arg,
RmwOp::Sub,
OperandSize::S8,
Some(ExtendKind::I32Extend8U),
)
}

fn visit_i32_atomic_rmw16_sub_u(&mut self, arg: MemArg) -> Self::Output {
self.emit_atomic_rmw(
&arg,
RmwOp::Sub,
OperandSize::S16,
Some(ExtendKind::I32Extend16U),
)
}

fn visit_i64_atomic_rmw8_sub_u(&mut self, arg: MemArg) -> Self::Output {
self.emit_atomic_rmw(
&arg,
RmwOp::Sub,
OperandSize::S8,
Some(ExtendKind::I64Extend8U),
)
}

fn visit_i64_atomic_rmw16_sub_u(&mut self, arg: MemArg) -> Self::Output {
self.emit_atomic_rmw(
&arg,
RmwOp::Sub,
OperandSize::S16,
Some(ExtendKind::I64Extend16U),
)
}

fn visit_i64_atomic_rmw32_sub_u(&mut self, arg: MemArg) -> Self::Output {
self.emit_atomic_rmw(
&arg,
RmwOp::Sub,
OperandSize::S32,
Some(ExtendKind::I64Extend32U),
)
}

wasmparser::for_each_visit_operator!(def_unsupported);
}

Expand Down