Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

winch x64 rmw sub #10008

Merged
merged 5 commits into from
Jan 16, 2025
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
Loading