Skip to content

Commit c72de0b

Browse files
authored
winch x64 rmw sub (bytecodealliance#10008)
* implement rmw sub for x64 in winch * fmt * fix tests after rebase * turn match into if-let * fix test
1 parent 529b6ad commit c72de0b

File tree

10 files changed

+316
-9
lines changed

10 files changed

+316
-9
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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 0x64
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+
;; andw $1, %cx
23+
;; cmpw $0, %cx
24+
;; jne 0x66
25+
;; 44: movl $0, %ecx
26+
;; movq 0x58(%r14), %r11
27+
;; movq (%r11), %rdx
28+
;; addq %rcx, %rdx
29+
;; negw %ax
30+
;; lock xaddw %ax, (%rdx)
31+
;; movzwl %ax, %eax
32+
;; addq $0x10, %rsp
33+
;; popq %rbp
34+
;; retq
35+
;; 64: ud2
36+
;; 66: ud2
Lines changed: 31 additions & 0 deletions
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
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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 0x5d
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+
;; andl $3, %ecx
23+
;; cmpl $0, %ecx
24+
;; jne 0x5f
25+
;; 42: movl $0, %ecx
26+
;; movq 0x58(%r14), %r11
27+
;; movq (%r11), %rdx
28+
;; addq %rcx, %rdx
29+
;; negl %eax
30+
;; lock xaddl %eax, (%rdx)
31+
;; addq $0x10, %rsp
32+
;; popq %rbp
33+
;; retq
34+
;; 5d: ud2
35+
;; 5f: ud2
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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 0x67
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+
;; andw $1, %cx
23+
;; cmpw $0, %cx
24+
;; jne 0x69
25+
;; 46: movl $0, %ecx
26+
;; movq 0x58(%r14), %r11
27+
;; movq (%r11), %rdx
28+
;; addq %rcx, %rdx
29+
;; negw %ax
30+
;; lock xaddw %ax, (%rdx)
31+
;; movzwq %ax, %rax
32+
;; addq $0x10, %rsp
33+
;; popq %rbp
34+
;; retq
35+
;; 67: ud2
36+
;; 69: ud2
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
;;! target = "x86_64"
2+
;;! test = "winch"
3+
4+
(module
5+
(memory 1 1 shared)
6+
(func (export "_start") (result i64)
7+
(i64.atomic.rmw32.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 0x61
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+
;; andl $3, %ecx
23+
;; cmpl $0, %ecx
24+
;; jne 0x63
25+
;; 44: movl $0, %ecx
26+
;; movq 0x58(%r14), %r11
27+
;; movq (%r11), %rdx
28+
;; addq %rcx, %rdx
29+
;; negl %eax
30+
;; lock xaddl %eax, (%rdx)
31+
;; movl %eax, %eax
32+
;; addq $0x10, %rsp
33+
;; popq %rbp
34+
;; retq
35+
;; 61: ud2
36+
;; 63: ud2
Lines changed: 31 additions & 0 deletions
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
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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 0x63
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+
;; andq $7, %rcx
23+
;; cmpq $0, %rcx
24+
;; jne 0x65
25+
;; 46: movl $0, %ecx
26+
;; movq 0x58(%r14), %r11
27+
;; movq (%r11), %rdx
28+
;; addq %rcx, %rdx
29+
;; negq %rax
30+
;; lock xaddq %rax, (%rdx)
31+
;; addq $0x10, %rsp
32+
;; popq %rbp
33+
;; retq
34+
;; 63: ud2
35+
;; 65: ud2

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,15 +1329,16 @@ impl Masm for MacroAssembler {
13291329
RmwOp::Add => {
13301330
self.asm
13311331
.lock_xadd(addr, operand.to_reg(), operand, size, flags);
1332-
match extend {
1333-
// It is only necessary to zero-extend when the operand is less than 32bits.
1334-
// x64 automatically zero-extend 32bits to 64bit.
1335-
Some(extend) => {
1336-
self.asm.movzx_rr(operand.to_reg(), operand, extend);
1337-
}
1338-
_ => (),
1339-
}
13401332
}
1333+
RmwOp::Sub => {
1334+
self.asm.neg(operand.to_reg(), operand, size);
1335+
self.asm
1336+
.lock_xadd(addr, operand.to_reg(), operand, size, flags);
1337+
}
1338+
}
1339+
1340+
if let Some(extend) = extend {
1341+
self.asm.movzx_rr(operand.to_reg(), operand, extend);
13411342
}
13421343
Ok(())
13431344
}

winch/codegen/src/masm.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,13 @@ macro_rules! def_unsupported {
286286
(emit I64AtomicRmw32AddU $($rest:tt)*) => {};
287287
(emit I64AtomicRmwAdd $($rest:tt)*) => {};
288288
(emit I8x16Shuffle $($rest:tt)*) => {};
289+
(emit I32AtomicRmw8SubU $($rest:tt)*) => {};
290+
(emit I32AtomicRmw16SubU $($rest:tt)*) => {};
291+
(emit I32AtomicRmwSub $($rest:tt)*) => {};
292+
(emit I64AtomicRmw8SubU $($rest:tt)*) => {};
293+
(emit I64AtomicRmw16SubU $($rest:tt)*) => {};
294+
(emit I64AtomicRmw32SubU $($rest:tt)*) => {};
295+
(emit I64AtomicRmwSub $($rest:tt)*) => {};
289296

290297
(emit $unsupported:tt $($rest:tt)*) => {$($rest)*};
291298
}
@@ -2325,13 +2332,71 @@ where
23252332
}
23262333

23272334
fn visit_i64_atomic_rmw32_add_u(&mut self, arg: MemArg) -> Self::Output {
2328-
self.emit_atomic_rmw(&arg, RmwOp::Add, OperandSize::S32, None)
2335+
self.emit_atomic_rmw(
2336+
&arg,
2337+
RmwOp::Add,
2338+
OperandSize::S32,
2339+
Some(ExtendKind::I64Extend32U),
2340+
)
23292341
}
23302342

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

2347+
fn visit_i32_atomic_rmw_sub(&mut self, arg: MemArg) -> Self::Output {
2348+
self.emit_atomic_rmw(&arg, RmwOp::Sub, OperandSize::S32, None)
2349+
}
2350+
2351+
fn visit_i64_atomic_rmw_sub(&mut self, arg: MemArg) -> Self::Output {
2352+
self.emit_atomic_rmw(&arg, RmwOp::Sub, OperandSize::S64, None)
2353+
}
2354+
2355+
fn visit_i32_atomic_rmw8_sub_u(&mut self, arg: MemArg) -> Self::Output {
2356+
self.emit_atomic_rmw(
2357+
&arg,
2358+
RmwOp::Sub,
2359+
OperandSize::S8,
2360+
Some(ExtendKind::I32Extend8U),
2361+
)
2362+
}
2363+
2364+
fn visit_i32_atomic_rmw16_sub_u(&mut self, arg: MemArg) -> Self::Output {
2365+
self.emit_atomic_rmw(
2366+
&arg,
2367+
RmwOp::Sub,
2368+
OperandSize::S16,
2369+
Some(ExtendKind::I32Extend16U),
2370+
)
2371+
}
2372+
2373+
fn visit_i64_atomic_rmw8_sub_u(&mut self, arg: MemArg) -> Self::Output {
2374+
self.emit_atomic_rmw(
2375+
&arg,
2376+
RmwOp::Sub,
2377+
OperandSize::S8,
2378+
Some(ExtendKind::I64Extend8U),
2379+
)
2380+
}
2381+
2382+
fn visit_i64_atomic_rmw16_sub_u(&mut self, arg: MemArg) -> Self::Output {
2383+
self.emit_atomic_rmw(
2384+
&arg,
2385+
RmwOp::Sub,
2386+
OperandSize::S16,
2387+
Some(ExtendKind::I64Extend16U),
2388+
)
2389+
}
2390+
2391+
fn visit_i64_atomic_rmw32_sub_u(&mut self, arg: MemArg) -> Self::Output {
2392+
self.emit_atomic_rmw(
2393+
&arg,
2394+
RmwOp::Sub,
2395+
OperandSize::S32,
2396+
Some(ExtendKind::I64Extend32U),
2397+
)
2398+
}
2399+
23352400
wasmparser::for_each_visit_operator!(def_unsupported);
23362401
}
23372402

0 commit comments

Comments
 (0)