Skip to content

Commit f565dba

Browse files
committed
implement rmw sub for x64 in winch
1 parent 3180071 commit f565dba

10 files changed

+290
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
;;! target = "x86_64"
2+
;;! test = "winch"
3+
4+
(module
5+
(memory 1 1 shared)
6+
(func (export "_start") (result i32)
7+
(i32.atomic.rmw16.sub_u (i32.const 0) (i32.const 42))))
8+
;; wasm[0]::function[0]:
9+
;; pushq %rbp
10+
;; movq %rsp, %rbp
11+
;; movq 8(%rdi), %r11
12+
;; movq 0x10(%r11), %r11
13+
;; addq $0x10, %r11
14+
;; cmpq %rsp, %r11
15+
;; ja 0x51
16+
;; 1c: movq %rdi, %r14
17+
;; subq $0x10, %rsp
18+
;; movq %rdi, 8(%rsp)
19+
;; movq %rsi, (%rsp)
20+
;; movl $0x2a, %eax
21+
;; movl $0, %ecx
22+
;; movq 0x58(%r14), %r11
23+
;; movq (%r11), %rdx
24+
;; addq %rcx, %rdx
25+
;; negw %ax
26+
;; lock xaddw %ax, (%rdx)
27+
;; movzwl %ax, %eax
28+
;; addq $0x10, %rsp
29+
;; popq %rbp
30+
;; retq
31+
;; 51: ud2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
;;! target = "x86_64"
2+
;;! test = "winch"
3+
4+
(module
5+
(memory 1 1 shared)
6+
(func (export "_start") (result i32)
7+
(i32.atomic.rmw8.sub_u (i32.const 0) (i32.const 42))))
8+
;; wasm[0]::function[0]:
9+
;; pushq %rbp
10+
;; movq %rsp, %rbp
11+
;; movq 8(%rdi), %r11
12+
;; movq 0x10(%r11), %r11
13+
;; addq $0x10, %r11
14+
;; cmpq %rsp, %r11
15+
;; ja 0x4f
16+
;; 1c: movq %rdi, %r14
17+
;; subq $0x10, %rsp
18+
;; movq %rdi, 8(%rsp)
19+
;; movq %rsi, (%rsp)
20+
;; movl $0x2a, %eax
21+
;; movl $0, %ecx
22+
;; movq 0x58(%r14), %r11
23+
;; movq (%r11), %rdx
24+
;; addq %rcx, %rdx
25+
;; negb %al
26+
;; lock xaddb %al, (%rdx)
27+
;; movzbl %al, %eax
28+
;; addq $0x10, %rsp
29+
;; popq %rbp
30+
;; retq
31+
;; 4f: ud2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
;;! target = "x86_64"
2+
;;! test = "winch"
3+
4+
(module
5+
(memory 1 1 shared)
6+
(func (export "_start") (result i32)
7+
(i32.atomic.rmw.sub (i32.const 0) (i32.const 42))))
8+
;; wasm[0]::function[0]:
9+
;; pushq %rbp
10+
;; movq %rsp, %rbp
11+
;; movq 8(%rdi), %r11
12+
;; movq 0x10(%r11), %r11
13+
;; addq $0x10, %r11
14+
;; cmpq %rsp, %r11
15+
;; ja 0x4c
16+
;; 1c: movq %rdi, %r14
17+
;; subq $0x10, %rsp
18+
;; movq %rdi, 8(%rsp)
19+
;; movq %rsi, (%rsp)
20+
;; movl $0x2a, %eax
21+
;; movl $0, %ecx
22+
;; movq 0x58(%r14), %r11
23+
;; movq (%r11), %rdx
24+
;; addq %rcx, %rdx
25+
;; negl %eax
26+
;; lock xaddl %eax, (%rdx)
27+
;; addq $0x10, %rsp
28+
;; popq %rbp
29+
;; retq
30+
;; 4c: ud2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
;;! target = "x86_64"
2+
;;! test = "winch"
3+
4+
(module
5+
(memory 1 1 shared)
6+
(func (export "_start") (result i64)
7+
(i64.atomic.rmw16.sub_u (i32.const 0) (i64.const 42))))
8+
;; wasm[0]::function[0]:
9+
;; pushq %rbp
10+
;; movq %rsp, %rbp
11+
;; movq 8(%rdi), %r11
12+
;; movq 0x10(%r11), %r11
13+
;; addq $0x10, %r11
14+
;; cmpq %rsp, %r11
15+
;; ja 0x54
16+
;; 1c: movq %rdi, %r14
17+
;; subq $0x10, %rsp
18+
;; movq %rdi, 8(%rsp)
19+
;; movq %rsi, (%rsp)
20+
;; movq $0x2a, %rax
21+
;; movl $0, %ecx
22+
;; movq 0x58(%r14), %r11
23+
;; movq (%r11), %rdx
24+
;; addq %rcx, %rdx
25+
;; negw %ax
26+
;; lock xaddw %ax, (%rdx)
27+
;; movzwq %ax, %rax
28+
;; addq $0x10, %rsp
29+
;; popq %rbp
30+
;; retq
31+
;; 54: ud2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
;;! target = "x86_64"
2+
;;! test = "winch"
3+
4+
(module
5+
(memory 1 1 shared)
6+
(func (export "_start") (result i64)
7+
(i64.atomic.rmw8.sub_u (i32.const 0) (i64.const 42))))
8+
;; wasm[0]::function[0]:
9+
;; pushq %rbp
10+
;; movq %rsp, %rbp
11+
;; movq 8(%rdi), %r11
12+
;; movq 0x10(%r11), %r11
13+
;; addq $0x10, %r11
14+
;; cmpq %rsp, %r11
15+
;; ja 0x52
16+
;; 1c: movq %rdi, %r14
17+
;; subq $0x10, %rsp
18+
;; movq %rdi, 8(%rsp)
19+
;; movq %rsi, (%rsp)
20+
;; movq $0x2a, %rax
21+
;; movl $0, %ecx
22+
;; movq 0x58(%r14), %r11
23+
;; movq (%r11), %rdx
24+
;; addq %rcx, %rdx
25+
;; negb %al
26+
;; lock xaddb %al, (%rdx)
27+
;; movzbq %al, %rax
28+
;; addq $0x10, %rsp
29+
;; popq %rbp
30+
;; retq
31+
;; 52: ud2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
;;! target = "x86_64"
2+
;;! test = "winch"
3+
4+
(module
5+
(memory 1 1 shared)
6+
(func (export "_start") (result i64)
7+
(i64.atomic.rmw8.sub_u (i32.const 0) (i64.const 42))))
8+
;; wasm[0]::function[0]:
9+
;; pushq %rbp
10+
;; movq %rsp, %rbp
11+
;; movq 8(%rdi), %r11
12+
;; movq 0x10(%r11), %r11
13+
;; addq $0x10, %r11
14+
;; cmpq %rsp, %r11
15+
;; ja 0x52
16+
;; 1c: movq %rdi, %r14
17+
;; subq $0x10, %rsp
18+
;; movq %rdi, 8(%rsp)
19+
;; movq %rsi, (%rsp)
20+
;; movq $0x2a, %rax
21+
;; movl $0, %ecx
22+
;; movq 0x58(%r14), %r11
23+
;; movq (%r11), %rdx
24+
;; addq %rcx, %rdx
25+
;; negb %al
26+
;; lock xaddb %al, (%rdx)
27+
;; movzbq %al, %rax
28+
;; addq $0x10, %rsp
29+
;; popq %rbp
30+
;; retq
31+
;; 52: ud2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
;;! target = "x86_64"
2+
;;! test = "winch"
3+
4+
(module
5+
(memory 1 1 shared)
6+
(func (export "_start") (result i64)
7+
(i64.atomic.rmw.sub (i32.const 0) (i64.const 42))))
8+
;; wasm[0]::function[0]:
9+
;; pushq %rbp
10+
;; movq %rsp, %rbp
11+
;; movq 8(%rdi), %r11
12+
;; movq 0x10(%r11), %r11
13+
;; addq $0x10, %r11
14+
;; cmpq %rsp, %r11
15+
;; ja 0x50
16+
;; 1c: movq %rdi, %r14
17+
;; subq $0x10, %rsp
18+
;; movq %rdi, 8(%rsp)
19+
;; movq %rsi, (%rsp)
20+
;; movq $0x2a, %rax
21+
;; movl $0, %ecx
22+
;; movq 0x58(%r14), %r11
23+
;; movq (%r11), %rdx
24+
;; addq %rcx, %rdx
25+
;; negq %rax
26+
;; lock xaddq %rax, (%rdx)
27+
;; addq $0x10, %rsp
28+
;; popq %rbp
29+
;; retq
30+
;; 50: ud2

winch/codegen/src/isa/x64/masm.rs

+19-13
Original file line numberDiff line numberDiff line change
@@ -1228,20 +1228,26 @@ impl Masm for MacroAssembler {
12281228
RmwOp::Add => {
12291229
self.asm
12301230
.lock_xadd(addr, operand.to_reg(), operand, size, flags);
1231-
match extend {
1232-
// It is only necessary to zero-extend when the operand is less than 32bits.
1233-
// x64 automatically zero-extend 32bits to 64bit.
1234-
Some(
1235-
extend @ (ExtendKind::I32Extend8S
1236-
| ExtendKind::I64Extend8S
1237-
| ExtendKind::I64Extend16S
1238-
| ExtendKind::I32Extend16S),
1239-
) => {
1240-
self.asm.movzx_rr(operand.to_reg(), operand, extend);
1241-
}
1242-
_ => (),
1243-
}
12441231
}
1232+
RmwOp::Sub => {
1233+
self.asm.neg(operand.to_reg(), operand, size);
1234+
self.asm
1235+
.lock_xadd(addr, operand.to_reg(), operand, size, flags);
1236+
},
1237+
}
1238+
1239+
match extend {
1240+
// It is only necessary to zero-extend when the operand is less than 32bits.
1241+
// x64 automatically zero-extend 32bits to 64bit.
1242+
Some(
1243+
extend @ (ExtendKind::I32Extend8S
1244+
| ExtendKind::I64Extend8S
1245+
| ExtendKind::I64Extend16S
1246+
| ExtendKind::I32Extend16S),
1247+
) => {
1248+
self.asm.movzx_rr(operand.to_reg(), operand, extend);
1249+
}
1250+
_ => (),
12451251
}
12461252

12471253
Ok(())

winch/codegen/src/masm.rs

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub(crate) enum MulWideKind {
5555
/// Type of operation for a read-modify-write instruction.
5656
pub(crate) enum RmwOp {
5757
Add,
58+
Sub,
5859
}
5960

6061
/// The direction to perform the memory move.

winch/codegen/src/visitor.rs

+55
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,13 @@ macro_rules! def_unsupported {
267267
(emit I64AtomicRmw16AddU $($rest:tt)*) => {};
268268
(emit I64AtomicRmw32AddU $($rest:tt)*) => {};
269269
(emit I64AtomicRmwAdd $($rest:tt)*) => {};
270+
(emit I32AtomicRmw8SubU $($rest:tt)*) => {};
271+
(emit I32AtomicRmw16SubU $($rest:tt)*) => {};
272+
(emit I32AtomicRmwSub $($rest:tt)*) => {};
273+
(emit I64AtomicRmw8SubU $($rest:tt)*) => {};
274+
(emit I64AtomicRmw16SubU $($rest:tt)*) => {};
275+
(emit I64AtomicRmw32SubU $($rest:tt)*) => {};
276+
(emit I64AtomicRmwSub $($rest:tt)*) => {};
270277

271278
(emit $unsupported:tt $($rest:tt)*) => {$($rest)*};
272279
}
@@ -2330,6 +2337,54 @@ where
23302337
self.atomic_rmw(&arg, RmwOp::Add, OperandSize::S64, None)
23312338
}
23322339

2340+
fn visit_i32_atomic_rmw_sub(&mut self, arg: MemArg) -> Self::Output {
2341+
self.atomic_rmw(&arg, RmwOp::Sub, OperandSize::S32, None)
2342+
}
2343+
2344+
fn visit_i64_atomic_rmw_sub(&mut self, arg: MemArg) -> Self::Output {
2345+
self.atomic_rmw(&arg, RmwOp::Sub, OperandSize::S64, None)
2346+
}
2347+
2348+
fn visit_i32_atomic_rmw8_sub_u(&mut self, arg: MemArg) -> Self::Output {
2349+
self.atomic_rmw(
2350+
&arg,
2351+
RmwOp::Sub,
2352+
OperandSize::S8,
2353+
Some(ExtendKind::I32Extend8S),
2354+
)
2355+
}
2356+
2357+
fn visit_i32_atomic_rmw16_sub_u(&mut self, arg: MemArg) -> Self::Output {
2358+
self.atomic_rmw(
2359+
&arg,
2360+
RmwOp::Sub,
2361+
OperandSize::S16,
2362+
Some(ExtendKind::I32Extend16S),
2363+
)
2364+
}
2365+
2366+
fn visit_i64_atomic_rmw8_sub_u(&mut self, arg: MemArg) -> Self::Output {
2367+
self.atomic_rmw(
2368+
&arg,
2369+
RmwOp::Sub,
2370+
OperandSize::S8,
2371+
Some(ExtendKind::I64Extend8S),
2372+
)
2373+
}
2374+
2375+
fn visit_i64_atomic_rmw16_sub_u(&mut self, arg: MemArg) -> Self::Output {
2376+
self.atomic_rmw(
2377+
&arg,
2378+
RmwOp::Sub,
2379+
OperandSize::S16,
2380+
Some(ExtendKind::I64Extend16S),
2381+
)
2382+
}
2383+
2384+
fn visit_i64_atomic_rmw32_sub_u(&mut self, arg: MemArg) -> Self::Output {
2385+
self.atomic_rmw(&arg, RmwOp::Sub, OperandSize::S32, None)
2386+
}
2387+
23332388
wasmparser::for_each_visit_operator!(def_unsupported);
23342389
}
23352390

0 commit comments

Comments
 (0)