Skip to content

Commit

Permalink
winch x64 rmw sub (#10008)
Browse files Browse the repository at this point in the history
* implement rmw sub for x64 in winch

* fmt

* fix tests after rebase

* turn match into if-let

* fix test
  • Loading branch information
MarinPostma authored Jan 16, 2025
1 parent 529b6ad commit c72de0b
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 9 deletions.
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 @@ -2325,13 +2332,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

0 comments on commit c72de0b

Please sign in to comment.