Skip to content

Commit 54311fd

Browse files
MaxGraeydcodeIO
authored andcommitted
Improve bswap implementation (AssemblyScript#323)
1 parent 63b64ba commit 54311fd

File tree

5 files changed

+491
-777
lines changed

5 files changed

+491
-777
lines changed

std/assembly/polyfills.ts

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,40 @@
11
export function bswap<T>(value: T): T {
2-
assert(sizeof<T>() == 1 || sizeof<T>() == 2 || sizeof<T>() == 4 || sizeof<T>() == 8);
2+
if (isInteger<T>()) {
3+
if (sizeof<T>() == 2) {
4+
return <T>((value << 8) | ((value >> 8) & <T>0x00FF));
5+
}
6+
if (sizeof<T>() == 4) {
7+
return <T>(
8+
rotl<u32>(<u32>value & 0xFF00FF00, 8) |
9+
rotr<u32>(<u32>value & 0x00FF00FF, 8)
10+
);
11+
}
12+
if (sizeof<T>() == 8) {
13+
let a = (<u64>value >> 8) & 0x00FF00FF00FF00FF;
14+
let b = (<u64>value & 0x00FF00FF00FF00FF) << 8;
15+
let v = a | b;
316

4-
if (sizeof<T>() == 2) {
5-
return bswap16<T>(value);
6-
}
7-
if (sizeof<T>() == 4) {
8-
return <T>(
9-
rotl<u32>(<u32>value & 0xFF00FF00, 8) |
10-
rotr<u32>(<u32>value & 0x00FF00FF, 8)
11-
);
12-
}
13-
if (sizeof<T>() == 8) {
14-
let a: u64 = (<u64>value >> 8) & 0x00FF00FF00FF00FF;
15-
let b: u64 = (<u64>value & 0x00FF00FF00FF00FF) << 8;
16-
let v: u64 = a | b;
17+
a = (v >> 16) & 0x0000FFFF0000FFFF;
18+
b = (v & 0x0000FFFF0000FFFF) << 16;
1719

18-
a = (v >> 16) & 0x0000FFFF0000FFFF;
19-
b = (v & 0x0000FFFF0000FFFF) << 16;
20-
21-
return <T>rotr<u64>(a | b, 32);
20+
return <T>rotr<u64>(a | b, 32);
21+
}
22+
return value;
2223
}
24+
assert(false);
2325
return value;
2426
}
2527

28+
@inline
2629
export function bswap16<T>(value: T): T {
27-
assert(sizeof<T>() == 1 || sizeof<T>() == 2 || sizeof<T>() == 4);
28-
29-
if (sizeof<T>() == 2 || sizeof<T>() == 4) {
30-
return <T>(((value << 8) & <T>0xFF00) | ((value >> 8) & <T>0x00FF) | (value & <T>0xFFFF0000));
30+
if (isInteger<T>() && sizeof<T>() <= 4) {
31+
if (sizeof<T>() == 2) {
32+
return <T>((value << 8) | ((value >> 8) & <T>0x00FF));
33+
} else if (sizeof<T>() == 4) {
34+
return <T>(((value << 8) & <T>0xFF00) | ((value >> 8) & <T>0x00FF) | (value & <T>0xFFFF0000));
35+
}
36+
return value;
3137
}
38+
assert(false);
3239
return value;
3340
}
Lines changed: 3 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,12 @@
11
(module
2-
(type $ii (func (param i32) (result i32)))
3-
(type $iiiiv (func (param i32 i32 i32 i32)))
42
(type $v (func))
5-
(import "env" "abort" (func $~lib/env/abort (param i32 i32 i32 i32)))
63
(memory $0 1)
7-
(data (i32.const 8) "\11\00\00\00~\00l\00i\00b\00/\00p\00o\00l\00y\00f\00i\00l\00l\00s\00.\00t\00s")
8-
(data (i32.const 48) "\10\00\00\00s\00t\00d\00/\00p\00o\00l\00y\00f\00i\00l\00l\00s\00.\00t\00s")
4+
(data (i32.const 8) "\10\00\00\00s\00t\00d\00/\00p\00o\00l\00y\00f\00i\00l\00l\00s\00.\00t\00s")
95
(table $0 1 anyfunc)
10-
(elem (i32.const 0) $null)
6+
(elem (i32.const 0) $start)
117
(export "memory" (memory $0))
128
(export "table" (table $0))
13-
(start $start)
14-
(func $~lib/polyfills/bswap16<u16> (; 1 ;) (type $ii) (param $0 i32) (result i32)
15-
(local $1 i32)
16-
i32.const 1
17-
tee_local $1
18-
i32.eqz
19-
if
20-
i32.const 0
21-
set_local $1
22-
end
23-
get_local $1
24-
i32.eqz
25-
if
26-
i32.const 0
27-
i32.const 8
28-
i32.const 27
29-
i32.const 2
30-
call $~lib/env/abort
31-
unreachable
32-
end
33-
i32.const 1
34-
tee_local $1
35-
if
36-
get_local $0
37-
i32.const 8
38-
i32.shl
39-
i32.const 65280
40-
i32.and
41-
get_local $0
42-
i32.const 65535
43-
i32.and
44-
i32.const 8
45-
i32.shr_u
46-
i32.or
47-
get_local $0
48-
i32.const -65536
49-
i32.and
50-
i32.or
51-
return
52-
end
53-
get_local $0
54-
)
55-
(func $~lib/polyfills/bswap16<i16> (; 2 ;) (type $ii) (param $0 i32) (result i32)
56-
(local $1 i32)
57-
i32.const 1
58-
tee_local $1
59-
i32.eqz
60-
if
61-
i32.const 0
62-
set_local $1
63-
end
64-
get_local $1
65-
i32.eqz
66-
if
67-
i32.const 0
68-
i32.const 8
69-
i32.const 27
70-
i32.const 2
71-
call $~lib/env/abort
72-
unreachable
73-
end
74-
i32.const 1
75-
tee_local $1
76-
if
77-
get_local $0
78-
i32.const 8
79-
i32.shl
80-
i32.const 65280
81-
i32.and
82-
get_local $0
83-
i32.const 16
84-
i32.shl
85-
i32.const 24
86-
i32.shr_s
87-
i32.const 255
88-
i32.and
89-
i32.or
90-
get_local $0
91-
i32.const -65536
92-
i32.and
93-
i32.or
94-
return
95-
end
96-
get_local $0
97-
)
98-
(func $start (; 3 ;) (type $v)
99-
i32.const 43707
100-
call $~lib/polyfills/bswap16<u16>
101-
i32.const 65535
102-
i32.and
103-
i32.const 48042
104-
i32.ne
105-
if
106-
i32.const 0
107-
i32.const 48
108-
i32.const 4
109-
i32.const 0
110-
call $~lib/env/abort
111-
unreachable
112-
end
113-
i32.const 43707
114-
call $~lib/polyfills/bswap16<i16>
115-
i32.const 65535
116-
i32.and
117-
i32.const 48042
118-
i32.ne
119-
if
120-
i32.const 0
121-
i32.const 48
122-
i32.const 5
123-
i32.const 0
124-
call $~lib/env/abort
125-
unreachable
126-
end
127-
i32.const 43707
128-
call $~lib/polyfills/bswap16<u16>
129-
i32.const 65535
130-
i32.and
131-
i32.const 48042
132-
i32.ne
133-
if
134-
i32.const 0
135-
i32.const 48
136-
i32.const 20
137-
i32.const 0
138-
call $~lib/env/abort
139-
unreachable
140-
end
141-
i32.const 43707
142-
call $~lib/polyfills/bswap16<i16>
143-
i32.const 65535
144-
i32.and
145-
i32.const 48042
146-
i32.ne
147-
if
148-
i32.const 0
149-
i32.const 48
150-
i32.const 21
151-
i32.const 0
152-
call $~lib/env/abort
153-
unreachable
154-
end
155-
)
156-
(func $null (; 4 ;) (type $v)
9+
(func $start (; 0 ;) (type $v)
15710
nop
15811
)
15912
)

tests/compiler/std/polyfills.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// bswap / bswap16 tests
22

3+
// check bswap<T> for i8/u8
4+
assert(bswap<u8>(<u8>0xaa) == <u8>0xaa);
5+
assert(bswap<i8>(<i8>0xaa) == <i8>0xaa);
6+
37
// check bswap<T> for i16/u16
48
assert(bswap<u16>(<u16>0xaabb) == <u16>0xbbaa);
59
assert(bswap<i16>(<i16>0xaabb) == <i16>0xbbaa);
@@ -16,6 +20,10 @@ assert(bswap<i64>(<i64>0x00112233aabbccdd) == <i64>0xddccbbaa33221100);
1620
assert(bswap<usize>(<usize>0xaabbccdd) == <usize>0xddccbbaa);
1721
assert(bswap<isize>(<isize>0xaabbccdd) == <isize>0xddccbbaa);
1822

23+
// check bswap16<T> for i8/u8
24+
assert(bswap16<u8>(<u8>0xaa) == <u8>0xaa);
25+
assert(bswap16<i8>(<i8>0xaa) == <i8>0xaa);
26+
1927
// check bswap16<T> for i16/u16
2028
assert(bswap16<u16>(<u16>0xaabb) == <u16>0xbbaa);
2129
assert(bswap16<i16>(<i16>0xaabb) == <i16>0xbbaa);

0 commit comments

Comments
 (0)