Source code

Revision control

Copy as Markdown

Other Tools

// |jit-test| skip-if: !wasmSimdEnabled()
// Do not include this in the preamble, it must be loaded after lib/wasm.js
load(scriptdir + "ad-hack-preamble.js")
// Simple unary operators. Place parameter in memory at offset 16,
// read the result at offset 0.
function expandConstantUnopInputs(op, memtype, inputs) {
let s = '';
let ident = 0;
for ( let a of inputs ) {
let constval = `${memtype.layoutName} ${a.map(jsValueToWasmName).join(' ')}`;
s += `
(func (export "run_const${ident}")
(v128.store (i32.const 0)
(${op} (v128.const ${constval}))))
`;
ident++;
}
return s;
}
function insAndMemUnop(op, memtype, resultmemtype, inputs) {
var ins = wasmEvalText(`
(module
(memory (export "mem") 1 1)
(func (export "run")
(v128.store (i32.const 0)
(call $doit (v128.load (i32.const 16)))))
(func $doit (param $a v128) (result v128)
(${op} (local.get $a)))
${expandConstantUnopInputs(op, memtype, inputs)})`);
var mem = new memtype(ins.exports.mem.buffer);
var resultmem = !resultmemtype || memtype == resultmemtype ? mem : new resultmemtype(ins.exports.mem.buffer);
return [ins, mem, resultmem];
}
function ineg(bits) { return (a) => sign_extend(!a ? a : -a,bits) }
function iabs(bits) { return (a) => zero_extend(a < 0 ? -a : a, bits) }
function fneg(a) { return -a }
function fabs(a) { return Math.abs(a) }
function fsqrt(a) { return Math.fround(Math.sqrt(Math.fround(a))) }
function dsqrt(a) { return Math.sqrt(a) }
function bitnot(a) { return (~a) & 255 }
function ffloor(x) { return Math.fround(Math.floor(x)) }
function fceil(x) { return Math.fround(Math.ceil(x)) }
function ftrunc(x) { return Math.fround(Math.sign(x)*Math.floor(Math.abs(x))) }
function fnearest(x) { return Math.fround(Math.round(x)) }
function dfloor(x) { return Math.floor(x) }
function dceil(x) { return Math.ceil(x) }
function dtrunc(x) { return Math.sign(x)*Math.floor(Math.abs(x)) }
function dnearest(x) { return Math.round(x) }
for ( let [op, memtype, rop, resultmemtype] of
[['i8x16.neg', Int8Array, ineg(8)],
['i16x8.neg', Int16Array, ineg(16)],
['i32x4.neg', Int32Array, ineg(32)],
['i64x2.neg', BigInt64Array, ineg(64)],
['i8x16.abs', Int8Array, iabs(8), Uint8Array],
['i16x8.abs', Int16Array, iabs(16), Uint16Array],
['i32x4.abs', Int32Array, iabs(32), Uint32Array],
['f32x4.neg', Float32Array, fneg],
['f64x2.neg', Float64Array, fneg],
['f32x4.abs', Float32Array, fabs],
['f64x2.abs', Float64Array, fabs],
['f32x4.sqrt', Float32Array, fsqrt],
['f64x2.sqrt', Float64Array, dsqrt],
['f32x4.ceil', Float32Array, fceil],
['f32x4.floor', Float32Array, ffloor],
['f32x4.trunc', Float32Array, ftrunc],
['f32x4.nearest', Float32Array, fnearest],
['f64x2.ceil', Float64Array, dceil],
['f64x2.floor', Float64Array, dfloor],
['f64x2.trunc', Float64Array, dtrunc],
['f64x2.nearest', Float64Array, dnearest],
['v128.not', Uint8Array, bitnot],
])
{
let [ins, mem, resultmem] = insAndMemUnop(op, memtype, resultmemtype, memtype.inputs);
let len = 16/memtype.BYTES_PER_ELEMENT;
let xs = iota(len);
let zero = xs.map(_ => 0);
let bitsForF32 = memtype == Float32Array ? new Uint32Array(mem.buffer) : null;
let bitsForF64 = memtype == Float64Array ? new BigInt64Array(mem.buffer) : null;
function testIt(a, r) {
set(mem, len, a);
ins.exports.run();
assertSame(get(resultmem, 0, len), r);
// Test signalling NaN superficially by replacing QNaN inputs with SNaN
if (bitsForF32 != null && a.some(isNaN)) {
a.forEach((x, i) => { if (isNaN(x)) { bitsForF32[len+i] = 0x7FA0_0000; } });
ins.exports.run();
assertSame(get(resultmem, 0, len), r);
}
if (bitsForF64 != null && a.some(isNaN)) {
a.forEach((x, i) => { if (isNaN(x)) { bitsForF64[len+i] = 0x7FF4_0000_0000_0000n; } });
ins.exports.run();
assertSame(get(resultmem, 0, len), r);
}
}
function testConstIt(i,r) {
set(resultmem, 0, zero);
ins.exports["run_const" + i]();
assertSame(get(resultmem, 0, len), r);
}
let i = 0;
for (let a of memtype.inputs) {
let r = xs.map((i) => rop(a[i]));
testIt(a, r);
testConstIt(i, r);
i++;
}
}