Improve bswap implementation (#323)

This commit is contained in:
Max Graey 2018-11-09 18:51:32 +02:00 committed by Daniel Wirtz
parent 63b64ba69e
commit 54311fd0ab
5 changed files with 494 additions and 780 deletions

View File

@ -1,33 +1,40 @@
export function bswap<T>(value: T): T {
assert(sizeof<T>() == 1 || sizeof<T>() == 2 || sizeof<T>() == 4 || sizeof<T>() == 8);
if (isInteger<T>()) {
if (sizeof<T>() == 2) {
return <T>((value << 8) | ((value >> 8) & <T>0x00FF));
}
if (sizeof<T>() == 4) {
return <T>(
rotl<u32>(<u32>value & 0xFF00FF00, 8) |
rotr<u32>(<u32>value & 0x00FF00FF, 8)
);
}
if (sizeof<T>() == 8) {
let a = (<u64>value >> 8) & 0x00FF00FF00FF00FF;
let b = (<u64>value & 0x00FF00FF00FF00FF) << 8;
let v = a | b;
if (sizeof<T>() == 2) {
return bswap16<T>(value);
}
if (sizeof<T>() == 4) {
return <T>(
rotl<u32>(<u32>value & 0xFF00FF00, 8) |
rotr<u32>(<u32>value & 0x00FF00FF, 8)
);
}
if (sizeof<T>() == 8) {
let a: u64 = (<u64>value >> 8) & 0x00FF00FF00FF00FF;
let b: u64 = (<u64>value & 0x00FF00FF00FF00FF) << 8;
let v: u64 = a | b;
a = (v >> 16) & 0x0000FFFF0000FFFF;
b = (v & 0x0000FFFF0000FFFF) << 16;
a = (v >> 16) & 0x0000FFFF0000FFFF;
b = (v & 0x0000FFFF0000FFFF) << 16;
return <T>rotr<u64>(a | b, 32);
return <T>rotr<u64>(a | b, 32);
}
return value;
}
assert(false);
return value;
}
@inline
export function bswap16<T>(value: T): T {
assert(sizeof<T>() == 1 || sizeof<T>() == 2 || sizeof<T>() == 4);
if (sizeof<T>() == 2 || sizeof<T>() == 4) {
return <T>(((value << 8) & <T>0xFF00) | ((value >> 8) & <T>0x00FF) | (value & <T>0xFFFF0000));
if (isInteger<T>() && sizeof<T>() <= 4) {
if (sizeof<T>() == 2) {
return <T>((value << 8) | ((value >> 8) & <T>0x00FF));
} else if (sizeof<T>() == 4) {
return <T>(((value << 8) & <T>0xFF00) | ((value >> 8) & <T>0x00FF) | (value & <T>0xFFFF0000));
}
return value;
}
assert(false);
return value;
}

View File

@ -1,159 +1,12 @@
(module
(type $ii (func (param i32) (result i32)))
(type $iiiiv (func (param i32 i32 i32 i32)))
(type $v (func))
(import "env" "abort" (func $~lib/env/abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 8) "\11\00\00\00~\00l\00i\00b\00/\00p\00o\00l\00y\00f\00i\00l\00l\00s\00.\00t\00s")
(data (i32.const 48) "\10\00\00\00s\00t\00d\00/\00p\00o\00l\00y\00f\00i\00l\00l\00s\00.\00t\00s")
(data (i32.const 8) "\10\00\00\00s\00t\00d\00/\00p\00o\00l\00y\00f\00i\00l\00l\00s\00.\00t\00s")
(table $0 1 anyfunc)
(elem (i32.const 0) $null)
(elem (i32.const 0) $start)
(export "memory" (memory $0))
(export "table" (table $0))
(start $start)
(func $~lib/polyfills/bswap16<u16> (; 1 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
i32.const 1
tee_local $1
i32.eqz
if
i32.const 0
set_local $1
end
get_local $1
i32.eqz
if
i32.const 0
i32.const 8
i32.const 27
i32.const 2
call $~lib/env/abort
unreachable
end
i32.const 1
tee_local $1
if
get_local $0
i32.const 8
i32.shl
i32.const 65280
i32.and
get_local $0
i32.const 65535
i32.and
i32.const 8
i32.shr_u
i32.or
get_local $0
i32.const -65536
i32.and
i32.or
return
end
get_local $0
)
(func $~lib/polyfills/bswap16<i16> (; 2 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
i32.const 1
tee_local $1
i32.eqz
if
i32.const 0
set_local $1
end
get_local $1
i32.eqz
if
i32.const 0
i32.const 8
i32.const 27
i32.const 2
call $~lib/env/abort
unreachable
end
i32.const 1
tee_local $1
if
get_local $0
i32.const 8
i32.shl
i32.const 65280
i32.and
get_local $0
i32.const 16
i32.shl
i32.const 24
i32.shr_s
i32.const 255
i32.and
i32.or
get_local $0
i32.const -65536
i32.and
i32.or
return
end
get_local $0
)
(func $start (; 3 ;) (type $v)
i32.const 43707
call $~lib/polyfills/bswap16<u16>
i32.const 65535
i32.and
i32.const 48042
i32.ne
if
i32.const 0
i32.const 48
i32.const 4
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 43707
call $~lib/polyfills/bswap16<i16>
i32.const 65535
i32.and
i32.const 48042
i32.ne
if
i32.const 0
i32.const 48
i32.const 5
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 43707
call $~lib/polyfills/bswap16<u16>
i32.const 65535
i32.and
i32.const 48042
i32.ne
if
i32.const 0
i32.const 48
i32.const 20
i32.const 0
call $~lib/env/abort
unreachable
end
i32.const 43707
call $~lib/polyfills/bswap16<i16>
i32.const 65535
i32.and
i32.const 48042
i32.ne
if
i32.const 0
i32.const 48
i32.const 21
i32.const 0
call $~lib/env/abort
unreachable
end
)
(func $null (; 4 ;) (type $v)
(func $start (; 0 ;) (type $v)
nop
)
)

View File

@ -1,5 +1,9 @@
// bswap / bswap16 tests
// check bswap<T> for i8/u8
assert(bswap<u8>(<u8>0xaa) == <u8>0xaa);
assert(bswap<i8>(<i8>0xaa) == <i8>0xaa);
// check bswap<T> for i16/u16
assert(bswap<u16>(<u16>0xaabb) == <u16>0xbbaa);
assert(bswap<i16>(<i16>0xaabb) == <i16>0xbbaa);
@ -16,6 +20,10 @@ assert(bswap<i64>(<i64>0x00112233aabbccdd) == <i64>0xddccbbaa33221100);
assert(bswap<usize>(<usize>0xaabbccdd) == <usize>0xddccbbaa);
assert(bswap<isize>(<isize>0xaabbccdd) == <isize>0xddccbbaa);
// check bswap16<T> for i8/u8
assert(bswap16<u8>(<u8>0xaa) == <u8>0xaa);
assert(bswap16<i8>(<i8>0xaa) == <i8>0xaa);
// check bswap16<T> for i16/u16
assert(bswap16<u16>(<u16>0xaabb) == <u16>0xbbaa);
assert(bswap16<i16>(<i16>0xaabb) == <i16>0xbbaa);

File diff suppressed because it is too large Load Diff

View File

@ -58,6 +58,10 @@
(global $std/typedarray/sub8 (mut i32) (i32.const 0))
(global $std/typedarray/arr32 (mut i32) (i32.const 0))
(global $std/typedarray/sub32 (mut i32) (i32.const 0))
(global $std/typedarray/multisubarr (mut i32) (i32.const 0))
(global $std/typedarray/multisubarr1 (mut i32) (i32.const 0))
(global $std/typedarray/multisubarr2 (mut i32) (i32.const 0))
(global $std/typedarray/multisubarr3 (mut i32) (i32.const 0))
(export "memory" (memory $0))
(export "table" (table $0))
(start $start)
@ -1103,9 +1107,12 @@
i32.load
i32.store
get_local $2
get_local $0
i32.load offset=4
get_local $3
i32.const 2
i32.shl
i32.add
i32.store offset=4
get_local $2
get_local $1
@ -1178,9 +1185,12 @@
i32.load
i32.store
get_local $1
get_local $0
i32.load offset=4
get_local $2
i32.const 3
i32.shl
i32.add
i32.store offset=4
get_local $1
get_local $3
@ -1955,47 +1965,64 @@
get_local $3
call $~lib/internal/typedarray/TypedArray<i8,i32>#fill
)
(func $~lib/typedarray/Int8Array#subarray (; 26 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
(func $~lib/typedarray/Int8Array#subarray (; 26 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
i32.const 1
get_local $0
i32.load offset=8
tee_local $1
tee_local $2
i32.const 1
get_local $1
i32.lt_s
select
set_local $2
i32.const 4
get_local $1
i32.const 4
get_local $1
i32.lt_s
select
tee_local $1
get_local $2
get_local $1
get_local $2
i32.gt_s
i32.lt_s
select
set_local $3
get_local $1
i32.const 0
i32.lt_s
if (result i32)
get_local $2
get_local $1
i32.add
tee_local $2
get_local $3
get_local $2
get_local $3
i32.gt_s
select
else
get_local $1
get_local $2
get_local $1
get_local $2
i32.lt_s
select
tee_local $2
get_local $3
get_local $2
get_local $3
i32.gt_s
select
end
set_local $1
i32.const 12
call $~lib/allocator/arena/__memory_allocate
tee_local $1
tee_local $2
get_local $0
i32.load
i32.store
get_local $1
get_local $2
get_local $0
i32.load offset=4
get_local $3
i32.add
i32.store offset=4
get_local $2
get_local $1
get_local $3
get_local $2
i32.sub
i32.store offset=8
get_local $1
get_local $2
)
(func $~lib/internal/typedarray/TypedArray<i32,i32>#fill (; 27 ;) (type $iiiii) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32)
(local $4 i32)
@ -2647,6 +2674,7 @@
unreachable
end
get_global $std/typedarray/arr8
i32.const 4
call $~lib/typedarray/Int8Array#subarray
set_global $std/typedarray/sub8
i32.const 1
@ -2907,6 +2935,198 @@
i32.const 134217727
call $~lib/internal/typedarray/TypedArray<i64,i64>#constructor
drop
i32.const 6
call $~lib/internal/typedarray/TypedArray<i8,i32>#constructor
set_global $std/typedarray/multisubarr
get_global $std/typedarray/multisubarr
i32.const 0
i32.const 1
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
get_global $std/typedarray/multisubarr
i32.const 1
i32.const 2
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
get_global $std/typedarray/multisubarr
i32.const 2
i32.const 3
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
get_global $std/typedarray/multisubarr
i32.const 3
i32.const 4
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
get_global $std/typedarray/multisubarr
i32.const 4
i32.const 5
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
get_global $std/typedarray/multisubarr
i32.const 5
i32.const 6
call $~lib/internal/typedarray/TypedArray<u8,u32>#__set
get_global $std/typedarray/multisubarr
i32.const 6
call $~lib/typedarray/Int8Array#subarray
set_global $std/typedarray/multisubarr1
get_global $std/typedarray/multisubarr1
i32.const 0
call $~lib/internal/typedarray/TypedArray<i8,i32>#__get
i32.const 255
i32.and
i32.const 2
i32.ne
if
i32.const 0
i32.const 8
i32.const 212
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr1
i32.load offset=8
i32.const 5
i32.ne
if
i32.const 0
i32.const 8
i32.const 213
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr1
i32.load offset=4
i32.const 1
i32.ne
if
i32.const 0
i32.const 8
i32.const 214
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr1
i32.load offset=8
i32.const 5
i32.ne
if
i32.const 0
i32.const 8
i32.const 215
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr1
i32.const 5
call $~lib/typedarray/Int8Array#subarray
set_global $std/typedarray/multisubarr2
get_global $std/typedarray/multisubarr2
i32.const 0
call $~lib/internal/typedarray/TypedArray<i8,i32>#__get
i32.const 255
i32.and
i32.const 3
i32.ne
if
i32.const 0
i32.const 8
i32.const 218
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr2
i32.load offset=8
i32.const 4
i32.ne
if
i32.const 0
i32.const 8
i32.const 219
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr2
i32.load offset=4
i32.const 2
i32.ne
if
i32.const 0
i32.const 8
i32.const 220
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr2
i32.load offset=8
i32.const 4
i32.ne
if
i32.const 0
i32.const 8
i32.const 221
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr2
i32.const 4
call $~lib/typedarray/Int8Array#subarray
set_global $std/typedarray/multisubarr3
get_global $std/typedarray/multisubarr3
i32.const 0
call $~lib/internal/typedarray/TypedArray<i8,i32>#__get
i32.const 255
i32.and
i32.const 4
i32.ne
if
i32.const 0
i32.const 8
i32.const 224
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr3
i32.load offset=8
i32.const 3
i32.ne
if
i32.const 0
i32.const 8
i32.const 225
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr3
i32.load offset=4
i32.const 3
i32.ne
if
i32.const 0
i32.const 8
i32.const 226
i32.const 0
call $~lib/env/abort
unreachable
end
get_global $std/typedarray/multisubarr3
i32.load offset=8
i32.const 3
i32.ne
if
i32.const 0
i32.const 8
i32.const 227
i32.const 0
call $~lib/env/abort
unreachable
end
)
(func $null (; 31 ;) (type $v)
nop