// |jit-test| --setpref=wasm_wide_arithmetic=true
let t = `
(module
(func (export
"doAddI128" )
;; (lhsLo lhsHi rhsLo rhsHi) -> (resultLo resultHi)
(param i64 i64 i64 i64) (result i64 i64)
local.get
0
local.get
1
local.get
2
local.get
3
i64.add128
)
(func (export
"doSubI128" )
;; (lhsLo lhsHi rhsLo rhsHi) -> (resultLo resultHi)
(param i64 i64 i64 i64) (result i64 i64)
local.get
0
local.get
1
local.get
2
local.get
3
i64.sub128
)
(func (export
"doMulI64WideU" )
;; (lhs rhs) -> (resultLo resultHi)
(param i64 i64) (result i64 i64)
local.get
0
local.get
1
i64.mul_wide_u
)
(func (export
"doMulI64WideS" )
;; (lhs rhs) -> (resultLo resultHi)
(param i64 i64) (result i64 i64)
local.get
0
local.get
1
i64.mul_wide_s
)
)`;
let i = wasmEvalText(t);
////////////////////////////////////////////////////////////////////////
// Some simple smoke tests
// 2^63
let x80 =
0 x8000000000000000n;
// "normalize" `x` so it falls into uint64_t range (a lame kludge)
function normalize(x) {
if (x <
0 n)
return x + x80 + x80;
return x;
}
function tryAddI128(a, b, c, d, expected) {
assertEq(expected.length,
2 );
let actual = i.exports.doAddI128(a, b, c, d);
assertEq(actual.length,
2 );
assertEq(normalize(actual[
0 ]), normalize(expected[
0 ]));
assertEq(normalize(actual[
1 ]), normalize(expected[
1 ]));
}
function trySubI128(a, b, c, d, expected) {
assertEq(expected.length,
2 );
let actual = i.exports.doSubI128(a, b, c, d);
assertEq(actual.length,
2 );
assertEq(normalize(actual[
0 ]), normalize(expected[
0 ]));
assertEq(normalize(actual[
1 ]), normalize(expected[
1 ]));
}
function tryMulI64WideU(a, b, expected) {
assertEq(expected.length,
2 );
let actual = i.exports.doMulI64WideU(a, b);
assertEq(actual.length,
2 );
assertEq(normalize(actual[
0 ]), normalize(expected[
0 ]));
assertEq(normalize(actual[
1 ]), normalize(expected[
1 ]));
}
function tryMulI64WideS(a, b, expected) {
assertEq(expected.length,
2 );
let actual = i.exports.doMulI64WideS(a, b);
assertEq(actual.length,
2 );
assertEq(normalize(actual[
0 ]), normalize(expected[
0 ]));
assertEq(normalize(actual[
1 ]), normalize(expected[
1 ]));
}
// Addition
// format is: --lhs-- --rhs-- result
// lo, hi, lo, hi, [lo, hi]
tryAddI128(
2 n,
1 n,
4 n,
3 n, [
6 n,
4 n]);
// no carry at midpoint
tryAddI128( x80,
22 n, x80,
33 n, [
0 n,
56 n]);
// carry at midpoint
// carry out of neither
tryAddI128(
0 x02a74ec1865d36e3n,
0 x30fe727e0ffbaf31n,
0 xb432733713c75e66n,
0 x457b20ce3d706ea3n,
[
0 xb6d9c1f89a249549n,
0 x7679934c4d6c1dd4n]);
// carry out of lo
tryAddI128(
0 xcd0e81861923459bn,
0 x30fe727e0ffbaf31n,
0 xb432733713c75e66n,
0 x457b20ce3d706ea3n,
[
0 x8140f4bd2ceaa401n,
0 x7679934c4d6c1dd5n]);
// carry out of hi
tryAddI128(
0 x02a74ec1865d36e3n,
0 xd74276b90c9d680bn,
0 xb432733713c75e66n,
0 x457b20ce3d706ea3n,
[
0 xb6d9c1f89a249549n,
0 x1cbd97874a0dd6aen]);
// carry out of both
tryAddI128(
0 xcd0e81861923459bn,
0 xd74276b90c9d680bn,
0 xb432733713c75e66n,
0 x457b20ce3d706ea3n,
[
0 x8140f4bd2ceaa401n,
0 x1cbd97874a0dd6afn]);
// Subtraction
// format is: --lhs-- --rhs-- result
// lo, hi, lo, hi, [lo, hi]
trySubI128(
88 n,
9999 n,
66 n,
4444 n, [
22 n,
5555 n]);
// no borrow at midpoint
trySubI128(
88 n,
9999 n,
99 n,
4444 n, [-
11 n,
5554 n]);
// borrow at midpoint
trySubI128(
0 x02a74ec1865d36e3n,
0 x30fe727e0ffbaf31n,
0 xb432733713c75e66n,
0 x457b20ce3d706ea3n,
[
5653384819931207805 n, -
1476246437253922675 n]);
trySubI128(
0 xcd0e81861923459bn,
0 x30fe727e0ffbaf31n,
0 xb432733713c75e66n,
0 x457b20ce3d706ea3n,
[
1791322484341729077 n, -
1476246437253922674 n]);
trySubI128(
0 x02a74ec1865d36e3n,
0 xd74276b90c9d680bn,
0 xb432733713c75e66n,
0 x457b20ce3d706ea3n,
[
5653384819931207805 n, -
7942284950858040985 n]);
trySubI128(
0 xcd0e81861923459bn,
0 xd74276b90c9d680bn,
0 xb432733713c75e66n,
0 x457b20ce3d706ea3n,
[
1791322484341729077 n, -
7942284950858040984 n]);
// Widening multiplies
// format is: -result-
// operand operand [hi, lo]
// Signed and unsigned produce the same result.
tryMulI64WideU(
123 n,
456 n, [
56088 n,
0 n]);
tryMulI64WideS(
123 n,
456 n, [
56088 n,
0 n]);
// Signed and unsigned produce the same result; but bits[127:64] are now used
tryMulI64WideU(
123999888777 n,
456777666555 n, [
8875542349269292115 n,
3070 n]);
tryMulI64WideS(
123999888777 n,
456777666555 n, [
8875542349269292115 n,
3070 n]);
// Signed and unsigned produce different results
tryMulI64WideU(
0 x8123ffffeeeeddddn,
456777666555 n,
[-
6687103016203617617 n,
230424036496 n]);
tryMulI64WideS(
0 x8123ffffeeeeddddn,
456777666555 n,
[
11759641057505933999 n,
18446743847355921557 n]);
// As above pair, but with operands swapped. Results should be the same
// as above.
tryMulI64WideU(
456777666555 n,
0 x8123ffffeeeeddddn,
[-
6687103016203617617 n,
230424036496 n]);
tryMulI64WideS(
456777666555 n,
0 x8123ffffeeeeddddn,
[
11759641057505933999 n,
18446743847355921557 n]);
////////////////////////////////////////////////////////////////////////
// Testcases from
// https://github.com/WebAssembly/wide-arithmetic/pull/22/commits/
// f292896bef63408a88d1dc4e56b2ac1cb8c530ab
// simple addition
tryAddI128(
0 n,
0 n,
0 n,
0 n, [
0 n,
0 n]);
tryAddI128(
0 n,
1 n,
1 n,
0 n, [
1 n,
1 n]);
tryAddI128(
1 n,
0 n, -
1 n,
0 n, [
0 n,
1 n]);
tryAddI128(
1 n,
1 n, -
1 n, -
1 n, [
0 n,
1 n]);
// simple subtraction
trySubI128(
0 n,
0 n,
0 n,
0 n, [
0 n,
0 n]);
trySubI128(
0 n,
0 n,
1 n,
0 n, [-
1 n, -
1 n]);
trySubI128(
0 n,
1 n,
1 n,
1 n, [-
1 n, -
1 n]);
trySubI128(
0 n,
0 n,
1 n,
1 n, [-
1 n, -
2 n]);
// simple mul_wide
tryMulI64WideS(
0 n,
0 n, [
0 n,
0 n]);
tryMulI64WideU(
0 n,
0 n, [
0 n,
0 n]);
tryMulI64WideS(
1 n,
1 n, [
1 n,
0 n]);
tryMulI64WideU(
1 n,
1 n, [
1 n,
0 n]);
tryMulI64WideS(-
1 n, -
1 n, [
1 n,
0 n]);
tryMulI64WideS(-
1 n,
1 n, [-
1 n, -
1 n]);
tryMulI64WideU(-
1 n,
1 n, [-
1 n,
0 n]);
// 20 randomly generated test cases for i64.add128
tryAddI128(-
2418420703207364752 n, -
1 n,
-
1 n, -
1 n,
[-
2418420703207364753 n, -
1 n]);
tryAddI128(
0 n,
0 n,
-
4579433644172935106 n, -
1 n,
[-
4579433644172935106 n, -
1 n]);
tryAddI128(
0 n,
0 n,
1 n, -
1 n,
[
1 n, -
1 n]);
tryAddI128(
1 n,
0 n,
1 n,
0 n,
[
2 n,
0 n]);
tryAddI128(-
1 n, -
1 n,
-
1 n, -
1 n,
[-
2 n, -
1 n]);
tryAddI128(
0 n, -
1 n,
1 n,
0 n,
[
1 n, -
1 n]);
tryAddI128(
0 n,
0 n,
0 n, -
1 n,
[
0 n, -
1 n]);
tryAddI128(
1 n,
0 n,
-
1 n, -
1 n,
[
0 n,
0 n]);
tryAddI128(
0 n,
6184727276166606191 n,
0 n,
1 n,
[
0 n,
6184727276166606192 n]);
tryAddI128(-
8434911321912688222 n, -
1 n,
1 n, -
1 n,
[-
8434911321912688221 n, -
2 n]);
tryAddI128(
1 n, -
1 n,
0 n, -
1 n,
[
1 n, -
2 n]);
tryAddI128(
1 n, -
5148941131328838092 n,
0 n,
0 n,
[
1 n, -
5148941131328838092 n]);
tryAddI128(
1 n,
1 n,
1 n,
0 n,
[
2 n,
1 n]);
tryAddI128(-
1 n, -
1 n,
-
3636740005180858631 n, -
1 n,
[-
3636740005180858632 n, -
1 n]);
tryAddI128(-
5529682780229988275 n, -
1 n,
0 n,
0 n,
[-
5529682780229988275 n, -
1 n]);
tryAddI128(
1 n, -
5381447440966559717 n,
1020031372481336745 n,
1 n,
[
1020031372481336746 n, -
5381447440966559716 n]);
tryAddI128(
1 n,
1 n,
0 n,
0 n,
[
1 n,
1 n]);
tryAddI128(-
9133888546939907356 n, -
1 n,
1 n,
1 n,
[-
9133888546939907355 n,
0 n]);
tryAddI128(-
4612047512704241719 n, -
1 n,
0 n, -
1 n,
[-
4612047512704241719 n, -
2 n]);
tryAddI128(
414720966820876428 n, -
1 n,
1 n,
0 n,
[
414720966820876429 n, -
1 n]);
// 20 randomly generated test cases for i64.sub128
trySubI128(
0 n, -
2459085471354756766 n,
-
9151153060221070927 n, -
1 n,
[
9151153060221070927 n, -
2459085471354756766 n]);
trySubI128(
4566502638724063423 n, -
4282658540409485563 n,
-
6884077310018979971 n, -
1 n,
[-
6996164124966508222 n, -
4282658540409485563 n]);
trySubI128(
1 n,
3118380319444903041 n,
0 n,
3283115686417695443 n,
[
1 n, -
164735366972792402 n]);
trySubI128(-
7208415241680161810 n, -
1 n,
1 n,
0 n,
[-
7208415241680161811 n, -
1 n]);
trySubI128(
0 n,
3944850126731328706 n,
1 n,
1 n,
[-
1 n,
3944850126731328704 n]);
trySubI128(
1 n, -
1 n,
-
1 n, -
1 n,
[
2 n, -
1 n]);
trySubI128(-
1 n, -
1 n,
4855833073346115923 n, -
6826437637438999645 n,
[-
4855833073346115924 n,
6826437637438999644 n]);
trySubI128(
1 n,
0 n,
-
1 n, -
1 n,
[
2 n,
0 n]);
trySubI128(
1 n,
0 n,
1 n,
0 n,
[
0 n,
0 n]);
trySubI128(-
1 n, -
1 n,
0 n,
0 n,
[-
1 n, -
1 n]);
trySubI128(
1 n, -
1 n,
-
6365475388498096428 n, -
1 n,
[
6365475388498096429 n, -
1 n]);
trySubI128(
6804238617560992346 n, -
1 n,
0 n, -
1 n,
[
6804238617560992346 n,
0 n]);
trySubI128(
0 n,
1 n,
1 n, -
7756145513466453619 n,
[-
1 n,
7756145513466453619 n]);
trySubI128(
1 n, -
1 n,
1 n,
1 n,
[
0 n, -
2 n]);
trySubI128(
0 n,
1 n,
1 n,
0 n,
[-
1 n,
0 n]);
trySubI128(
1 n,
5602881641763648953 n,
-
2110589244314239080 n, -
1 n,
[
2110589244314239081 n,
5602881641763648953 n]);
trySubI128(
0 n,
1 n,
-
1 n, -
1 n,
[
1 n,
1 n]);
trySubI128(
0 n, -
1 n,
3553816990259121806 n, -
2105235417856431622 n,
[-
3553816990259121806 n,
2105235417856431620 n]);
trySubI128(
1861102705894987245 n,
1 n,
3713781778534059871 n,
1 n,
[-
1852679072639072626 n, -
1 n]);
trySubI128(
0 n, -
1 n,
1 n,
1832524486821761762 n,
[-
1 n, -
1832524486821761764 n]);
// 20 randomly generated test cases for i64.mul_wide_s
tryMulI64WideS(
1 n,
1 n,
[
1 n,
0 n]);
tryMulI64WideS(
0 n,
6287758211025156705 n,
[
0 n,
0 n]);
tryMulI64WideS(-
6643537319803451357 n,
1 n,
[-
6643537319803451357 n, -
1 n]);
tryMulI64WideS(-
2483565146858803428 n,
0 n,
[
0 n,
0 n]);
tryMulI64WideS(
1 n,
1 n,
[
1 n,
0 n]);
tryMulI64WideS(-
3838951433439430085 n,
3471602925362676030 n,
[
5186941893001237834 n, -
722475195264825124 n]);
tryMulI64WideS(-
8262495286814853129 n,
7883241869666573970 n,
[-
8557189786755031842 n, -
3530988912334554469 n]);
tryMulI64WideS(
4278371902407959701 n,
1 n,
[
4278371902407959701 n,
0 n]);
tryMulI64WideS(-
8852706149487089182 n, -
1 n,
[
8852706149487089182 n,
0 n]);
tryMulI64WideS(
1 n, -
1 n,
[-
1 n, -
1 n]);
tryMulI64WideS(-
1 n, -
4329244561838653387 n,
[
4329244561838653387 n,
0 n]);
tryMulI64WideS(-
1 n, -
1 n,
[
1 n,
0 n]);
tryMulI64WideS(
697896157315764057 n,
1 n,
[
697896157315764057 n,
0 n]);
tryMulI64WideS(
1 n,
1 n,
[
1 n,
0 n]);
tryMulI64WideS(-
1 n,
0 n,
[
0 n,
0 n]);
tryMulI64WideS(
0 n, -
3769664482072947073 n,
[
0 n,
0 n]);
tryMulI64WideS(
1 n,
8414291037346403854 n,
[
8414291037346403854 n,
0 n]);
tryMulI64WideS(
1 n, -
1 n,
[-
1 n, -
1 n]);
tryMulI64WideS(
5014655679779318485 n, -
5080037812563681985 n,
[
2842857627777395563 n, -
1380983027057486843 n]);
tryMulI64WideS(
0 n,
1 n,
[
0 n,
0 n]);
// 20 randomly generated test cases for i64.mul_wide_u
tryMulI64WideU(-
4734436040338162711 n,
0 n,
[
0 n,
0 n]);
tryMulI64WideU(
1 n,
0 n,
[
0 n,
0 n]);
tryMulI64WideU(
3270597527173764279 n,
6636648075495406358 n,
[-
5430303818902260550 n,
1176674035141685826 n]);
tryMulI64WideU(-
7771814344630108151 n,
1 n,
[-
7771814344630108151 n,
0 n]);
tryMulI64WideU(
1 n,
0 n,
[
0 n,
0 n]);
tryMulI64WideU(
1 n, -
7864138787704962081 n,
[-
7864138787704962081 n,
0 n]);
tryMulI64WideU(
1 n,
518555141550256010 n,
[
518555141550256010 n,
0 n]);
tryMulI64WideU(
1 n, -
1 n,
[-
1 n,
0 n]);
tryMulI64WideU(
1118900477321231571 n, -
1 n,
[-
1118900477321231571 n,
1118900477321231570 n]);
tryMulI64WideU(-
1 n,
0 n,
[
0 n,
0 n]);
tryMulI64WideU(-
5586890671027490027 n,
1 n,
[-
5586890671027490027 n,
0 n]);
tryMulI64WideU(
0 n,
3603850799751152505 n,
[
0 n,
0 n]);
tryMulI64WideU(-
1 n, -
1 n,
[
1 n,
18446744073709551614 n]);
tryMulI64WideU(
0 n,
1 n,
[
0 n,
0 n]);
tryMulI64WideU(-
7344082851774441644 n,
3896439839137544024 n,
[
5738542512914895072 n,
2345175459296971666 n]);
tryMulI64WideU(
0 n,
0 n,
[
0 n,
0 n]);
tryMulI64WideU(
616395976148874061 n,
0 n,
[
0 n,
0 n]);
tryMulI64WideU(
2810729703362889816 n, -
1 n,
[-
2810729703362889816 n,
2810729703362889815 n]);
tryMulI64WideU(
1 n, -
1 n,
[-
1 n,
0 n]);
tryMulI64WideU(
1 n,
0 n,
[
0 n,
0 n]);
// assert overlong encodings for each instruction's binary encoding are
// accepted
let wasmBytes =
new Uint8Array([
0 x00,
0 x61,
0 x73,
0 x6d,
0 x01,
0 x00,
0 x00,
0 x00,
0 x01,
0 x11,
// type section, 17 bytes
0 x02,
// 2 count
0 x60,
// type0 = function
0 x04,
0 x7e,
0 x7e,
0 x7e,
0 x7e,
// 4 params - all i64
0 x02,
0 x7e,
0 x7e,
// 2 results - both i64
0 x60,
// type1 = function
0 x02,
0 x7e,
0 x7e,
// 2 params - both i64
0 x02,
0 x7e,
0 x7e,
// 2 results - both i64
0 x03,
0 x05,
// function section, 5 byte
0 x04,
// 4 count
0 x00,
0 x00,
0 x01,
0 x01,
// types of each function (0, 0, 1, 1)
0 x07,
0 x3d,
// export section 0x3d bytes
0 x04,
// 4 count
0 x0a,
0 x69,
0 x36,
0 x34,
0 x5f,
0 x61,
0 x64,
0 x64,
0 x31,
0 x32,
0 x38,
0 x00,
0 x00,
// i64_add128 which is function 0
0 x0a,
0 x69,
0 x36,
0 x34,
0 x5f,
0 x73,
0 x75,
0 x62,
0 x31,
0 x32,
0 x38,
0 x00,
0 x01,
// i64_add128 which is function 1
0 x0e,
0 x69,
0 x36,
0 x34,
0 x5f,
0 x6d,
0 x75,
0 x6c,
0 x5f,
0 x77,
0 x69,
0 x64,
0 x65,
0 x5f,
0 x73,
0 x00,
0 x02,
// i64_mul_wide_s which is function 2
0 x0e,
0 x69,
0 x36,
0 x34,
0 x5f,
0 x6d,
0 x75,
0 x6c,
0 x5f,
0 x77,
0 x69,
0 x64,
0 x65,
0 x5f,
0 x75,
0 x00,
0 x03,
// i64_mul_wide_u which is function 3
0 x0a,
0 x37,
// code section + byte length
0 x04,
// 4 count
0 x0e,
// byte length
0 x00,
// no locals
0 x20,
0 x00,
// local.get 0
0 x20,
0 x01,
// local.get 1
0 x20,
0 x02,
// local.get 2
0 x20,
0 x03,
// local.get 3
0 xfc,
0 x93,
0 x80,
0 x00,
// i64.add128 (overlong)
0 x0b,
// end
0 x0d,
// byte length
0 x00,
// no locals
0 x20,
0 x00,
// local.get 0
0 x20,
0 x01,
// local.get 1
0 x20,
0 x02,
// local.get 2
0 x20,
0 x03,
// local.get 3
0 xfc,
0 x94,
0 x00,
// i64.sub128 (overlong)
0 x0b,
// end
0 x0c,
// byte length
0 x00,
// no locals
0 x20,
0 x00,
// local.get 0
0 x20,
0 x01,
// local.get 1
0 xfc,
0 x95,
0 x80,
0 x80,
0 x80,
0 x00,
// i64.mul_wide_s (overlong)
0 x0b,
// end
0 x0b,
// byte length
0 x00,
// no locals
0 x20,
0 x00,
// local.get 0
0 x20,
0 x01,
// local.get 1
0 xfc,
0 x96,
0 x80,
0 x80,
0 x00,
// i64.mul_wide_u (overlong)
0 x0b
// end
]);
let wasmModule =
new WebAssembly.Module(wasmBytes);
let wasmInstance =
new WebAssembly.Instance(wasmModule, {});
let res = wasmInstance.exports.i64_add128(
1 n,
2 n,
3 n,
4 n);
assertEq(res[
0 ],
4 n);
assertEq(res[
1 ],
6 n);
res = wasmInstance.exports.i64_sub128(
2 n,
5 n,
1 n,
2 n);
assertEq(res[
0 ],
1 n);
assertEq(res[
1 ],
3 n);
res = wasmInstance.exports.i64_mul_wide_s(
1 n, -
2 n);
assertEq(res[
0 ], -
2 n);
assertEq(res[
1 ], -
1 n);
res = wasmInstance.exports.i64_mul_wide_u(
3 n,
2 n);
assertEq(res[
0 ],
6 n);
assertEq(res[
1 ],
0 n);
// some invalid types for these instructions
assertErrorMessage(() => wasmEvalText(`
(module
(func (param i64 i64 i64 i64) (result i64)
local.get
0
local.get
1
local.get
2
local.get
3
i64.add128)
)`), Error, /unused values not explicitly dropped by end of block/);
assertErrorMessage(() => wasmEvalText(`
(module
(func (param i64 i64 i64) (result i64 i64)
local.get
0
local.get
1
local.get
2
i64.add128)
)`), Error, /popping value from empty stack/);
assertErrorMessage(() => wasmEvalText(`
(module
(func (param i64 i64 i64 i64) (result i64)
local.get
0
local.get
1
local.get
2
local.get
3
i64.sub128)
)`), Error, /unused values not explicitly dropped by end of block/);
assertErrorMessage(() => wasmEvalText(`
(module
(func (param i64 i64 i64) (result i64 i64)
local.get
0
local.get
1
local.get
2
i64.sub128)
)`), Error, /popping value from empty stack/);
assertErrorMessage(() => wasmEvalText(`
(module
(func (param i64 i64) (result i64)
local.get
0
local.get
1
i64.mul_wide_s)
)`), Error, /unused values not explicitly dropped by end of block/);
assertErrorMessage(() => wasmEvalText(`
(module
(func (param i64) (result i64 i64)
local.get
0
i64.mul_wide_s)
)`), Error, /popping value from empty stack/);
assertErrorMessage(() => wasmEvalText(`
(module
(func (param i64 i64) (result i64)
local.get
0
local.get
1
i64.mul_wide_u)
)`), Error, /unused values not explicitly dropped by end of block/);
assertErrorMessage(() => wasmEvalText(`
(module
(func (param i64) (result i64 i64)
local.get
0
i64.mul_wide_u)
)`), Error, /popping value from empty stack/);
Messung V0.5 in Prozent C=93 H=97 G=94
¤ Dauer der Verarbeitung: 0.6 Sekunden
¤
*© Formatika GbR, Deutschland