From 20d37a6f2fa87887ca68540e83f1b017217caf8f Mon Sep 17 00:00:00 2001
From: dtig <dtig@users.noreply.github.com>
Date: Mon, 18 Apr 2016 11:26:15 -0700
Subject: [PATCH] Add SIMD test suite and utility functions (#442)

---
 harness/simdUtilities.js                   | 426 +++++++++++++++++++++
 test/built-ins/Simd/AUTHORS                |  12 +
 test/built-ins/Simd/all_true.js            |  29 ++
 test/built-ins/Simd/any_true.js            |  29 ++
 test/built-ins/Simd/bit_conversion.js      |  40 ++
 test/built-ins/Simd/bit_preservation.js    |  27 ++
 test/built-ins/Simd/check.js               |  35 ++
 test/built-ins/Simd/constructor.js         |  27 ++
 test/built-ins/Simd/float_operators.js     |  39 ++
 test/built-ins/Simd/from.js                |  34 ++
 test/built-ins/Simd/from_bits.js           |  31 ++
 test/built-ins/Simd/loadn.js               |  94 +++++
 test/built-ins/Simd/logical_operators.js   |  20 +
 test/built-ins/Simd/negate.js              |  14 +
 test/built-ins/Simd/not.js                 |  20 +
 test/built-ins/Simd/numerical_operators.js |  40 ++
 test/built-ins/Simd/operators.js           |  58 +++
 test/built-ins/Simd/replace_lane.js        |  40 ++
 test/built-ins/Simd/round_trip.js          |  15 +
 test/built-ins/Simd/saturate.js            |  26 ++
 test/built-ins/Simd/select.js              |  30 ++
 test/built-ins/Simd/shift_operator.js      |  55 +++
 test/built-ins/Simd/shuffle.js             |  59 +++
 test/built-ins/Simd/storen.js              |  86 +++++
 test/built-ins/Simd/swizzle.js             |  48 +++
 25 files changed, 1334 insertions(+)
 create mode 100644 harness/simdUtilities.js
 create mode 100644 test/built-ins/Simd/AUTHORS
 create mode 100644 test/built-ins/Simd/all_true.js
 create mode 100644 test/built-ins/Simd/any_true.js
 create mode 100644 test/built-ins/Simd/bit_conversion.js
 create mode 100644 test/built-ins/Simd/bit_preservation.js
 create mode 100644 test/built-ins/Simd/check.js
 create mode 100644 test/built-ins/Simd/constructor.js
 create mode 100644 test/built-ins/Simd/float_operators.js
 create mode 100644 test/built-ins/Simd/from.js
 create mode 100644 test/built-ins/Simd/from_bits.js
 create mode 100644 test/built-ins/Simd/loadn.js
 create mode 100644 test/built-ins/Simd/logical_operators.js
 create mode 100644 test/built-ins/Simd/negate.js
 create mode 100644 test/built-ins/Simd/not.js
 create mode 100644 test/built-ins/Simd/numerical_operators.js
 create mode 100644 test/built-ins/Simd/operators.js
 create mode 100644 test/built-ins/Simd/replace_lane.js
 create mode 100644 test/built-ins/Simd/round_trip.js
 create mode 100644 test/built-ins/Simd/saturate.js
 create mode 100644 test/built-ins/Simd/select.js
 create mode 100644 test/built-ins/Simd/shift_operator.js
 create mode 100644 test/built-ins/Simd/shuffle.js
 create mode 100644 test/built-ins/Simd/storen.js
 create mode 100644 test/built-ins/Simd/swizzle.js

diff --git a/harness/simdUtilities.js b/harness/simdUtilities.js
new file mode 100644
index 0000000000..efb4cd2d59
--- /dev/null
+++ b/harness/simdUtilities.js
@@ -0,0 +1,426 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+function minNum(x, y) {
+  return x != x ? y :
+         y != y ? x :
+         Math.min(x, y);
+}
+
+function maxNum(x, y) {
+  return x != x ? y :
+         y != y ? x :
+         Math.max(x, y);
+}
+
+function sameValue(x, y) {
+  if (x == y)
+    return x != 0 || y != 0 || (1/x == 1/y);
+
+  return x != x && y != y;
+}
+
+function binaryMul(a, b) { return a * b; }
+var binaryImul;
+if (typeof Math.imul !== "undefined") {
+  binaryImul = Math.imul;
+} else {
+  binaryImul = function(a, b) {
+    var ah = (a >>> 16) & 0xffff;
+    var al = a & 0xffff;
+    var bh = (b >>> 16) & 0xffff;
+    var bl = b & 0xffff;
+    // the shift by 0 fixes the sign on the high part
+    // the final |0 converts the unsigned value into a signed value
+    return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0)|0);
+  };
+}
+
+var _f32x4 = new Float32Array(4);
+var _f64x2 = new Float64Array(_f32x4.buffer);
+var _i32x4 = new Int32Array(_f32x4.buffer);
+var _i16x8 = new Int16Array(_f32x4.buffer);
+var _i8x16 = new Int8Array(_f32x4.buffer);
+var _ui32x4 = new Uint32Array(_f32x4.buffer);
+var _ui16x8 = new Uint16Array(_f32x4.buffer);
+var _ui8x16 = new Uint8Array(_f32x4.buffer);
+
+var float32x4 = {
+  name: "Float32x4",
+  fn: SIMD.Float32x4,
+  floatLane: true,
+  signed: true,
+  numerical: true,
+  lanes: 4,
+  laneSize: 4,
+  interestingValues: [0, -0, 1, -1, 0.9, -0.9, 1.414, 0x7F, -0x80, -0x8000,
+  -0x80000000, 0x7FFF, 0x7FFFFFFF, Infinity, -Infinity, NaN],
+  view: Float32Array,
+  buffer: _f32x4,
+  mulFn: binaryMul,
+}
+
+var int32x4 = {
+  name: "Int32x4",
+  fn: SIMD.Int32x4,
+  intLane: true,
+  signed: true,
+  numerical: true,
+  logical: true,
+  lanes: 4,
+  laneSize: 4,
+  minVal: -0x80000000,
+  maxVal: 0x7FFFFFFF,
+  interestingValues: [0, 1, -1, 0x40000000, 0x7FFFFFFF, -0x80000000],
+  view: Int32Array,
+  buffer: _i32x4,
+  mulFn: binaryImul,
+}
+
+var int16x8 = {
+  name: "Int16x8",
+  fn: SIMD.Int16x8,
+  intLane: true,
+  signed: true,
+  numerical: true,
+  logical: true,
+  lanes: 8,
+  laneSize: 2,
+  laneMask: 0xFFFF,
+  minVal: -0x8000,
+  maxVal: 0x7FFF,
+  interestingValues: [0, 1, -1, 0x4000, 0x7FFF, -0x8000],
+  view: Int16Array,
+  buffer: _i16x8,
+  mulFn: binaryMul,
+}
+
+var int8x16 = {
+  name: "Int8x16",
+  fn: SIMD.Int8x16,
+  intLane: true,
+  signed: true,
+  numerical: true,
+  logical: true,
+  lanes: 16,
+  laneSize: 1,
+  laneMask: 0xFF,
+  minVal: -0x80,
+  maxVal: 0x7F,
+  interestingValues: [0, 1, -1, 0x40, 0x7F, -0x80],
+  view: Int8Array,
+  buffer: _i8x16,
+  mulFn: binaryMul,
+}
+
+var uint32x4 = {
+  name: "Uint32x4",
+  fn: SIMD.Uint32x4,
+  intLane: true,
+  unsigned: true,
+  numerical: true,
+  logical: true,
+  lanes: 4,
+  laneSize: 4,
+  minVal: 0,
+  maxVal: 0xFFFFFFFF,
+  interestingValues: [0, 1, 0x40000000, 0x7FFFFFFF, 0xFFFFFFFF],
+  view: Uint32Array,
+  buffer: _ui32x4,
+  mulFn: binaryImul,
+}
+
+var uint16x8 = {
+  name: "Uint16x8",
+  fn: SIMD.Uint16x8,
+  intLane: true,
+  unsigned: true,
+  numerical: true,
+  logical: true,
+  lanes: 8,
+  laneSize: 2,
+  laneMask: 0xFFFF,
+  minVal: 0,
+  maxVal: 0xFFFF,
+  interestingValues: [0, 1, 0x4000, 0x7FFF, 0xFFFF],
+  view: Uint16Array,
+  buffer: _ui16x8,
+  mulFn: binaryMul,
+}
+
+var uint8x16 = {
+  name: "Uint8x16",
+  fn: SIMD.Uint8x16,
+  intLane: true,
+  unsigned: true,
+  numerical: true,
+  logical: true,
+  lanes: 16,
+  laneSize: 1,
+  laneMask: 0xFF,
+  minVal: 0,
+  maxVal: 0xFF,
+  interestingValues: [0, 1, 0x40, 0x7F, 0xFF],
+  view: Int8Array,
+  buffer: _ui8x16,
+  mulFn: binaryMul,
+}
+
+var bool32x4 = {
+  name: "Bool32x4",
+  fn: SIMD.Bool32x4,
+  boolLane: true,
+  logical: true,
+  lanes: 4,
+  laneSize: 4,
+  interestingValues: [true, false],
+}
+
+var bool16x8 = {
+  name: "Bool16x8",
+  fn: SIMD.Bool16x8,
+  boolLane: true,
+  logical: true,
+  lanes: 8,
+  laneSize: 2,
+  interestingValues: [true, false],
+}
+
+var bool8x16 = {
+  name: "Bool8x16",
+  fn: SIMD.Bool8x16,
+  boolLane: true,
+  logical: true,
+  lanes: 16,
+  laneSize: 1,
+  interestingValues: [true, false],
+}
+
+// Filter functions.
+function isFloatType(type) { return type.floatLane; }
+function isIntType(type) { return type.intLane; }
+function isBoolType(type) { return type.boolLane; }
+function isNumerical(type) { return type.numerical; }
+function isLogical(type) { return type.logical; }
+function isSigned(type) { return type.signed; }
+function isSignedIntType(type) { return type.intLane && type.signed; }
+function isUnsignedIntType(type) { return type.intLane && type.unsigned; }
+function isSmallIntType(type) { return type.intLane && type.lanes >= 8; }
+function isSmallUnsignedIntType(type) {
+  return type.intLane && type.unsigned && type.lanes >= 8;
+}
+function hasLoadStore123(type) { return !type.boolLane && type.lanes == 4; }
+
+// Each SIMD type has a corresponding Boolean SIMD type, which is returned by
+// relational ops.
+float32x4.boolType = int32x4.boolType = uint32x4.boolType = bool32x4;
+int16x8.boolType = uint16x8.boolType = bool16x8;
+int8x16.boolType = uint8x16.boolType = bool8x16;
+
+// SIMD fromTIMD types.
+float32x4.from = [int32x4, uint32x4];
+int32x4.from = [float32x4];
+int16x8.from = [];
+int8x16.from = [];
+uint32x4.from = [float32x4];
+uint16x8.from = [int16x8];
+uint8x16.from = [int8x16];
+
+// SIMD fromBits types.
+float32x4.fromBits = [int32x4, int16x8, int8x16, uint32x4, uint16x8, uint8x16];
+int32x4.fromBits = [float32x4, int16x8, int8x16, uint32x4, uint16x8, uint8x16];
+int16x8.fromBits = [float32x4, int32x4, int8x16, uint32x4, uint16x8, uint8x16];
+int8x16.fromBits = [float32x4, int32x4, int16x8, uint32x4, uint16x8, uint8x16];
+uint32x4.fromBits = [float32x4, int32x4, int16x8, int8x16, uint16x8, uint8x16];
+uint16x8.fromBits = [float32x4, int32x4, int16x8, int8x16, uint32x4, uint8x16];
+uint8x16.fromBits = [float32x4, int32x4, int16x8, int8x16, uint32x4, uint16x8];
+
+var simdTypes = [float32x4,
+                 int32x4, int16x8, int8x16,
+                 uint32x4, uint16x8, uint8x16,
+                 bool32x4, bool16x8, bool8x16];
+
+if (typeof simdPhase2 !== "undefined") {
+  var float64x2 = {
+    name: "Float64x2",
+    fn: SIMD.Float64x2,
+    floatLane: true,
+    signed: true,
+    numerical: true,
+    lanes: 2,
+    laneSize: 8,
+    interestingValues: [0, -0, 1, -1, 1.414, 0x7F, -0x80, -0x8000, -0x80000000,
+    0x7FFF, 0x7FFFFFFF, Infinity, -Infinity, NaN],
+    view: Float64Array,
+    buffer: _f64x2,
+    mulFn: binaryMul,
+  }
+
+  var bool64x2 = {
+    name: "Bool64x2",
+    fn: SIMD.Bool64x2,
+    boolLane: true,
+    lanes: 2,
+    laneSize: 8,
+    interestingValues: [true, false],
+  }
+
+  float64x2.boolType = bool64x2;
+
+  float32x4.fromBits.push(float64x2);
+  int32x4.fromBits.push(float64x2);
+  int16x8.fromBits.push(float64x2);
+  int8x16.fromBits.push(float64x2);
+  uint32x4.fromBits.push(float64x2);
+  uint16x8.fromBits.push(float64x2);
+  uint8x16.fromBits.push(float64x2);
+
+  float64x2.fromBits = [float32x4, int32x4, int16x8, int8x16,
+  uint32x4, uint16x8, uint8x16];
+
+  int32x4.fromBits = [float32x4, int16x8, int8x16, uint32x4,
+  uint16x8, uint8x16];
+  int16x8.fromBits = [float32x4, int32x4, int8x16, uint32x4,
+  uint16x8, uint8x16];
+  int8x16.fromBits = [float32x4, int32x4, int16x8, uint32x4,
+  uint16x8, uint8x16];
+  uint32x4.fromBits = [float32x4, int32x4, int16x8, int8x16,
+  uint16x8, uint8x16];
+  uint16x8.fromBits = [float32x4, int32x4, int16x8, int8x16,
+  uint32x4, uint8x16];
+  uint8x16.fromBits = [float32x4, int32x4, int16x8, int8x16,
+  uint32x4, uint16x8];
+
+  simdTypes.push(float64x2);
+  simdTypes.push(bool64x2);
+}
+
+// SIMD utility functions.
+
+// Create a value for testing, with vanilla lane values, i.e. [0, 1, 2, ..]
+// for numeric types, [false, true, true, ..] for boolean types. These test
+// values shouldn't contain NaNs or other "interesting" values.
+function createTestValue(type) {
+  var lanes = [];
+  for (var i = 0; i < type.lanes; i++)
+    lanes.push(i);
+  return type.fn.apply(type.fn, lanes);
+}
+
+function createSplatValue(type, v) {
+  var lanes = [];
+  for (var i = 0; i < type.lanes; i++)
+    lanes.push(v);
+  return type.fn.apply(type.fn, lanes);
+}
+
+// SIMD reference functions.
+
+// Returns converted array buffer value of specified type.
+function simdConvert(type, value) {
+  if (type.buffer === undefined) return !!value;  // bool types
+  type.buffer[0] = value;
+  return type.buffer[0];
+}
+
+function checkValue(type, a, expect) {
+  var fail = false;
+  for (var i = 0; i < type.lanes; i++) {
+    var v = type.fn.extractLane(a, i);
+    var ev = simdConvert(type, expect(i));
+    if (!sameValue(ev, v) && Math.abs(ev - v) >= 0.00001)
+      fail = true;
+  }
+  if (fail) {
+    var lanes = [];
+    for (var i = 0; i < type.lanes; i++){
+      lanes.push(simdConvert(type, expect(i)));
+    }
+    $ERROR("expected SIMD." + type.name + "(" + lanes +
+        ") but found " + a.toString());
+  }
+}
+
+// SIMD reference functions.
+
+// Reference implementation of toLocaleString.
+function simdToLocaleString(type, value) {
+  value = type.fn.check(value);
+  var str = "SIMD." + type.name + "(";
+  str += type.fn.extractLane(value, 0).toLocaleString();
+  for (var i = 1; i < type.lanes; i++) {
+    str += "," + type.fn.extractLane(value, i).toLocaleString();
+  }
+  return str + ")";
+}
+
+function equalInt32x4(a, b) {
+  assert.sameValue(SIMD.Int32x4.extractLane(a, 0),
+      SIMD.Int32x4.extractLane(b, 0));
+  assert.sameValue(SIMD.Int32x4.extractLane(a, 1),
+      SIMD.Int32x4.extractLane(b, 1));
+  assert.sameValue(SIMD.Int32x4.extractLane(a, 2),
+      SIMD.Int32x4.extractLane(b, 2));
+  assert.sameValue(SIMD.Int32x4.extractLane(a, 3),
+      SIMD.Int32x4.extractLane(b, 3));
+}
+
+// Compare unary op's behavior to ref op at each lane.
+function testUnaryOp(type, op, refOp) {
+  assert.sameValue("function", typeof type.fn[op]);
+  for (var v of type.interestingValues) {
+    var expected = simdConvert(type, refOp(v));
+    var a = type.fn.splat(v);
+    var result = type.fn[op](a);
+    checkValue(type, result, function(index) { return expected; });
+  }
+}
+
+// Compare binary op's behavior to ref op at each lane with the Cartesian
+// product of the given values.
+function testBinaryOp(type, op, refOp) {
+  assert.sameValue("function", typeof type.fn[op]);
+  var zero = type.fn();
+  for (var av of type.interestingValues) {
+    for (var bv of type.interestingValues) {
+      var expected = simdConvert(type, refOp(simdConvert(type, av),
+            simdConvert(type, bv)));
+      var a = type.fn.splat(av);
+      var b = type.fn.splat(bv);
+      var result = type.fn[op](a, b);
+      checkValue(type, result, function(index) { return expected; });
+    }
+  }
+}
+
+// Compare relational op's behavior to ref op at each lane with the Cartesian
+// product of the given values.
+function testRelationalOp(type, op, refOp) {
+  assert.sameValue("function", typeof type.fn[op]);
+  var zero = type.fn();
+  for (var av of type.interestingValues) {
+    for (var bv of type.interestingValues) {
+      var expected = refOp(simdConvert(type, av), simdConvert(type, bv));
+      var a = type.fn.splat(av);
+      var b = type.fn.splat(bv);
+      var result = type.fn[op](a, b);
+      checkValue(type.boolType, result, function(index) { return expected; });
+    }
+  }
+}
+
+// Test utilities.
+var currentName = "<global>";
+var skipValueTests = false;
+
+function testSimdFunction(name, func) {
+  currentName = name;
+  if (typeof skipValueTests !== "undefined" && skipValueTests &&
+      name.indexOf("value semantics") != -1) return;
+  try {
+    func();
+  } catch (e) {
+    e.message += " (Testing with " + name + ".)";
+    throw e;
+  }
+}
diff --git a/test/built-ins/Simd/AUTHORS b/test/built-ins/Simd/AUTHORS
new file mode 100644
index 0000000000..f566d7e48b
--- /dev/null
+++ b/test/built-ins/Simd/AUTHORS
@@ -0,0 +1,12 @@
+Arun Purushan <arun.etm@gmail.com>
+Benjamin Bouvier <public@benj.me>
+Bill Budge <bbudge@chromium.org>
+Dan Ehrenberg <littledan@chromium.org>
+Dan Gohman <sunfish@mozilla.com>
+Deepti Gandluri <gdeepti@google.com>
+Florian Scholz <elchi3@elchi3.de>
+Heidi Pan <heidi.pan@intel.com>
+Jakob Stoklund Olesen <jolesen@mozilla.com>
+John McCutchan <john@johnmccutchan.com>
+Ningxin Hu <ningxin.hu@intel.com>
+Peter Jensen <peter.jensen@intel.com>
diff --git a/test/built-ins/Simd/all_true.js b/test/built-ins/Simd/all_true.js
new file mode 100644
index 0000000000..698c64d6e5
--- /dev/null
+++ b/test/built-ins/Simd/all_true.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-all-true
+description: AllTrue returns true if all the SIMDElements are true.
+includes: [simdUtilities.js]
+---*/
+
+function testAllTrue(type) {
+  assert.sameValue('function', typeof type.fn.allTrue);
+  // All lanes 'true'.
+  var a = type.fn.splat(true);
+  assert(type.fn.allTrue(a));
+  // One lane 'false'.
+  for (var i = 0; i < type.lanes; i++) {
+    a = type.fn.replaceLane(a, i, false);
+    assert(!type.fn.allTrue(a));
+  }
+  // All lanes 'false'.
+  a = type.fn.splat(false);
+  assert(!type.fn.allTrue(a));
+}
+
+simdTypes.filter(isBoolType).forEach(function(type) {
+  testSimdFunction(type.name + ' allTrue', function() {
+    testAllTrue(type, 'allTrue');
+  });
+});
diff --git a/test/built-ins/Simd/any_true.js b/test/built-ins/Simd/any_true.js
new file mode 100644
index 0000000000..0412c800c3
--- /dev/null
+++ b/test/built-ins/Simd/any_true.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-any-true
+description: AllTrue returns true if all the SIMDElements are true.
+includes: [simdUtilities.js]
+---*/
+
+function testAnyTrue(type) {
+  assert.sameValue('function', typeof type.fn.anyTrue);
+  // All lanes 'false'.
+  var a = type.fn.splat(false);
+  assert(!type.fn.anyTrue(a));
+  // One lane 'true'.
+  for (var i = 0; i < type.lanes; i++) {
+    a = type.fn.replaceLane(a, i, true);
+    assert(type.fn.anyTrue(a));
+  }
+  // All lanes 'true'.
+  a = type.fn.splat(true);
+  assert(type.fn.anyTrue(a));
+}
+
+simdTypes.filter(isBoolType).forEach(function(type) {
+  testSimdFunction(type.name + ' anyTrue', function() {
+    testAnyTrue(type, 'anyTrue');
+  });
+});
diff --git a/test/built-ins/Simd/bit_conversion.js b/test/built-ins/Simd/bit_conversion.js
new file mode 100644
index 0000000000..e5fceb73d1
--- /dev/null
+++ b/test/built-ins/Simd/bit_conversion.js
@@ -0,0 +1,40 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: pending
+description: Tests Float32x4 Int32x4 bit conversion.
+includes: [simdUtilities.js]
+---*/
+
+testSimdFunction('Float32x4 Int32x4 bit conversion', function() {
+  var m = SIMD.Int32x4(0x3F800000, 0x40000000, 0x40400000, 0x40800000);
+  var n = SIMD.Float32x4.fromInt32x4Bits(m);
+  assert.sameValue(1.0, SIMD.Float32x4.extractLane(n, 0));
+  assert.sameValue(2.0, SIMD.Float32x4.extractLane(n, 1));
+  assert.sameValue(3.0, SIMD.Float32x4.extractLane(n, 2));
+  assert.sameValue(4.0, SIMD.Float32x4.extractLane(n, 3));
+  n = SIMD.Float32x4(5.0, 6.0, 7.0, 8.0);
+  m = SIMD.Int32x4.fromFloat32x4Bits(n);
+  assert.sameValue(0x40A00000, SIMD.Int32x4.extractLane(m, 0));
+  assert.sameValue(0x40C00000, SIMD.Int32x4.extractLane(m, 1));
+  assert.sameValue(0x40E00000, SIMD.Int32x4.extractLane(m, 2));
+  assert.sameValue(0x41000000, SIMD.Int32x4.extractLane(m, 3));
+  // Flip sign using bit-wise operators.
+  n = SIMD.Float32x4(9.0, 10.0, 11.0, 12.0);
+  m = SIMD.Int32x4(0x80000000, 0x80000000, 0x80000000, 0x80000000);
+  var nMask = SIMD.Int32x4.fromFloat32x4Bits(n);
+  nMask = SIMD.Int32x4.xor(nMask, m); // flip sign.
+  n = SIMD.Float32x4.fromInt32x4Bits(nMask);
+  assert.sameValue(-9.0, SIMD.Float32x4.extractLane(n, 0));
+  assert.sameValue(-10.0, SIMD.Float32x4.extractLane(n, 1));
+  assert.sameValue(-11.0, SIMD.Float32x4.extractLane(n, 2));
+  assert.sameValue(-12.0, SIMD.Float32x4.extractLane(n, 3));
+  nMask = SIMD.Int32x4.fromFloat32x4Bits(n);
+  nMask = SIMD.Int32x4.xor(nMask, m); // flip sign.
+  n = SIMD.Float32x4.fromInt32x4Bits(nMask);
+  assert.sameValue(9.0, SIMD.Float32x4.extractLane(n, 0));
+  assert.sameValue(10.0, SIMD.Float32x4.extractLane(n, 1));
+  assert.sameValue(11.0, SIMD.Float32x4.extractLane(n, 2));
+  assert.sameValue(12.0, SIMD.Float32x4.extractLane(n, 3));
+});
diff --git a/test/built-ins/Simd/bit_preservation.js b/test/built-ins/Simd/bit_preservation.js
new file mode 100644
index 0000000000..fb345d6385
--- /dev/null
+++ b/test/built-ins/Simd/bit_preservation.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: pending
+description: Tests SIMD load and store bit preservation.
+includes: [simdUtilities.js]
+---*/
+
+testSimdFunction('Float32x4 Int32x4 load/store bit preservation', function() {
+   // NaNs should stay unmodified when storing and loading to Float32Array
+  var taf32 = new Float32Array(4);
+  var tai32 = new Int32Array(4);
+  var i4a, i4b;
+  i4a = SIMD.Int32x4(0x7fc00000,0x7fe00000,0x7ff00000,0x7ff80000);
+  SIMD.Int32x4.store(taf32, 0, i4a);
+  i4b = SIMD.Int32x4.load(taf32, 0);
+  equalInt32x4(i4a, i4b);
+
+  // NaNs should stay unmodified when loading as Float32x4 and
+  // storing as Int32x4
+  SIMD.Int32x4.store(taf32, 0, i4a);
+  var f4 = SIMD.Float32x4.load(taf32, 0);
+  SIMD.Float32x4.store(tai32, 0, f4);
+  i4b = SIMD.Int32x4.load(tai32, 0);
+  equalInt32x4(i4a, i4b);
+});
diff --git a/test/built-ins/Simd/check.js b/test/built-ins/Simd/check.js
new file mode 100644
index 0000000000..c73ca4d4eb
--- /dev/null
+++ b/test/built-ins/Simd/check.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-check
+description: Checks if a SIMDTypeDescriptor is not a SIMDDescriptor.
+includes: [simdUtilities.js]
+---*/
+
+function testCheck(type) {
+  assert.sameValue('function', typeof type.fn.check);
+  // Other SIMD types shouldn't check for this type.
+  var a = type.fn();
+  for (var otherType of simdTypes) {
+    if (otherType === type) {
+      var result = type.fn.check(a);
+      checkValue(type, result, function(index) {
+        return type.fn.extractLane(a, index);
+      });
+      assert.sameValue(a, type.fn.check(a));
+    } else {
+      assert.throws(TypeError, function() { otherType.check(a); });
+    }
+  }
+  // Neither should other types.
+  for (var x of [ {}, "", 0, 1, true, false, undefined, null, NaN, Infinity]) {
+    assert.throws(TypeError, function() { type.fn.check(x); });
+  }
+}
+
+simdTypes.forEach(function(type) {
+  testSimdFunction(type.name + ' check', function() {
+    testCheck(type);
+  });
+});
diff --git a/test/built-ins/Simd/constructor.js b/test/built-ins/Simd/constructor.js
new file mode 100644
index 0000000000..d71d0a5efe
--- /dev/null
+++ b/test/built-ins/Simd/constructor.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-wrapper
+description: Test the constructor and splat with the given lane values.
+includes: [simdUtilities.js]
+---*/
+
+function testConstructor(type) {
+  assert.sameValue('function', typeof type.fn);
+  assert.sameValue('function', typeof type.fn.splat);
+  for (var v of type.interestingValues) {
+    var expected = simdConvert(type, v);
+    var result = createSplatValue(type, v);
+    checkValue(type, result, function(index) { return expected; });
+    // splat.
+    result = type.fn.splat(v);
+    checkValue(type, result, function(index) { return expected; });
+  }
+}
+
+simdTypes.forEach(function(type) {
+  testSimdFunction(type.name + ' constructor', function() {
+    testConstructor(type);
+  });
+});
diff --git a/test/built-ins/Simd/float_operators.js b/test/built-ins/Simd/float_operators.js
new file mode 100644
index 0000000000..37a55c8e5b
--- /dev/null
+++ b/test/built-ins/Simd/float_operators.js
@@ -0,0 +1,39 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: constructor-properties
+description: Test floating point SIMD operations.
+includes: [simdUtilities.js]
+---*/
+
+simdTypes.filter(isFloatType).forEach(function(type) {
+  testSimdFunction(type.name + ' div', function() {
+    testBinaryOp(type, 'div', function(a, b) { return a / b; });
+  });
+  testSimdFunction(type.name + ' abs', function() {
+    testUnaryOp(type, 'abs', Math.abs);
+  });
+  testSimdFunction(type.name + ' min', function() {
+    testBinaryOp(type, 'min', Math.min);
+  });
+  testSimdFunction(type.name + ' max', function() {
+    testBinaryOp(type, 'max', Math.max);
+  });
+  testSimdFunction(type.name + ' minNum', function() {
+    testBinaryOp(type, 'minNum', minNum);
+  });
+  testSimdFunction(type.name + ' maxNum', function() {
+    testBinaryOp(type, 'maxNum', maxNum);
+  });
+  testSimdFunction(type.name + ' sqrt', function() {
+    testUnaryOp(type, 'sqrt', function(a) { return Math.sqrt(a); });
+  });
+  testSimdFunction(type.name + ' reciprocalApproximation', function() {
+    testUnaryOp(type, 'reciprocalApproximation', function(a) { return 1 / a; });
+  });
+  testSimdFunction(type.name + ' reciprocalSqrtApproximation', function() {
+    testUnaryOp(type, 'reciprocalSqrtApproximation', function(a) {
+      return 1 / Math.sqrt(a); });
+  });
+})
diff --git a/test/built-ins/Simd/from.js b/test/built-ins/Simd/from.js
new file mode 100644
index 0000000000..ad67c6854b
--- /dev/null
+++ b/test/built-ins/Simd/from.js
@@ -0,0 +1,34 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-to-timd-logical
+description: Tests From<type> functions.
+includes: [simdUtilities.js]
+---*/
+
+function testFrom(toType, fromType, name) {
+  assert.sameValue('function', typeof toType.fn[name]);
+  for (var v of fromType.interestingValues) {
+    var fromValue = createSplatValue(fromType, v);
+    v = Math.trunc(simdConvert(fromType, v));
+    if (toType.minVal !== undefined &&
+        !(toType.minVal <= v && v <= toType.maxVal)) {
+      assert.throws(RangeError, function() { toType.fn[name](fromValue) });
+    } else {
+      v = simdConvert(toType, v);
+      var result = toType.fn[name](fromValue);
+      checkValue(toType, result, function(index) { return v; });
+    }
+  }
+}
+
+simdTypes.forEach(function(toType) {
+  if (!toType.from) return;
+  for (var fromType of toType.from) {
+    var fn = 'from' + fromType.name;
+    testSimdFunction(toType.name + ' ' + fn, function() {
+      testFrom(toType, fromType, fn);
+    });
+  }
+});
diff --git a/test/built-ins/Simd/from_bits.js b/test/built-ins/Simd/from_bits.js
new file mode 100644
index 0000000000..5a6f130b41
--- /dev/null
+++ b/test/built-ins/Simd/from_bits.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-to-timd
+description: From<type>Bits functions.
+includes: [simdUtilities.js]
+---*/
+
+function testFromBits(toType, fromType, name) {
+  assert.sameValue('function', typeof toType.fn[name]);
+  for (var v of fromType.interestingValues) {
+    var fromValue = createSplatValue(fromType, v);
+    var result = toType.fn[name](fromValue);
+    for (var i = 0; i < fromType.lanes; i++)
+      fromType.buffer[i] = fromType.fn.extractLane(fromValue, i);
+    checkValue(toType, result, function(index) {
+      return toType.buffer[index];
+    });
+  }
+}
+
+simdTypes.forEach(function(toType) {
+  if (!toType.fromBits) return;
+  for (var fromType of toType.fromBits) {
+    var fn = 'from' + fromType.name + 'Bits';
+    testSimdFunction(toType.name + ' ' + fn, function() {
+      testFromBits(toType, fromType, fn);
+    });
+  }
+});
diff --git a/test/built-ins/Simd/loadn.js b/test/built-ins/Simd/loadn.js
new file mode 100644
index 0000000000..616a959bf9
--- /dev/null
+++ b/test/built-ins/Simd/loadn.js
@@ -0,0 +1,94 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-load-from-tarray
+description: Tests SIMD load functions.
+includes: [simdUtilities.js]
+---*/
+
+function testLoad(type, name, count) {
+  var loadFn = type.fn[name];
+  assert.sameValue('function', typeof loadFn);
+  var bufLanes = 2 * type.lanes;  // Test all alignments.
+  var bufSize = bufLanes * type.laneSize + 8;  // Extra for over-alignment test.
+  var ab = new ArrayBuffer(bufSize);
+  var buf = new type.view(ab);
+  for (var i = 0; i < bufLanes; i++) buf[i] = i; // Number buffer sequentially.
+  // Test aligned loads.
+  for (var i = 0; i < type.lanes; i++) {
+    var a = loadFn(buf, i);
+    checkValue(type, a, function(index) {
+      return index < count ? i + index : 0;
+    });
+  }
+
+  // Test index coercions
+  // Unlike typedArray[index], non-canonical strings are allowed here.
+  checkValue(type, loadFn(buf, "0"),
+      function(index) { return index < count ? index : 0; });
+  checkValue(type, loadFn(buf, " -0.0 "),
+      function(index) { return index < count ? index : 0; });
+  checkValue(type, loadFn(buf, "00"),
+      function(index) { return index < count ? index : 0; });
+  checkValue(type, loadFn(buf, false),
+      function(index) { return index < count ? index : 0; });
+  checkValue(type, loadFn(buf, null),
+      function(index) { return index < count ? index : 0; });
+  checkValue(type, loadFn(buf, "01"),
+      function(index) { return index < count ? 1 + index : 0; });
+  checkValue(type, loadFn(buf, " +1e0"),
+      function(index) { return index < count ? 1 + index : 0; });
+  checkValue(type, loadFn(buf, true),
+      function(index) { return index < count ? 1 + index : 0; });
+
+  // Test the 2 possible over-alignments.
+  var f64 = new Float64Array(ab);
+  var stride = 8 / type.laneSize;
+  for (var i = 0; i < 1; i++) {
+    var a = loadFn(f64, i);
+    checkValue(type, a, function(index) {
+      return index < count ? stride * i + index : 0;
+    });
+  }
+  // Test the 7 possible mis-alignments.
+  var i8 = new Int8Array(ab);
+  for (var misalignment = 1; misalignment < 8; misalignment++) {
+    // Shift the buffer up by 1 byte.
+    for (var i = i8.length - 1; i > 0; i--)
+      i8[i] = i8[i - 1];
+    var a = loadFn(i8, misalignment);
+    checkValue(type, a, function(index) {
+      return index < count ? i + index : 0;
+    });
+  }
+
+  function testIndexCheck(buf, index, err) {
+    assert.throws(err, function () { loadFn(buf, index); });
+  }
+  testIndexCheck(buf, -1, RangeError);
+  testIndexCheck(buf, 0.7, RangeError);
+  testIndexCheck(buf, -0.1, RangeError);
+  testIndexCheck(buf, NaN, RangeError);
+  testIndexCheck(buf, bufSize / type.laneSize - count + 1, RangeError);
+  testIndexCheck(buf.buffer, 1, TypeError);
+  testIndexCheck(buf, "a", RangeError);
+}
+
+simdTypes.filter(isNumerical).forEach(function(type) {
+  testSimdFunction(type.name + ' load', function() {
+    testLoad(type, 'load', type.lanes);
+  });
+});
+
+simdTypes.filter(hasLoadStore123).forEach(function(type) {
+  testSimdFunction(type.name + ' load1', function() {
+    testLoad(type, 'load1', 1);
+  });
+  testSimdFunction(type.name + ' load2', function() {
+    testLoad(type, 'load2', 2);
+  });
+  testSimdFunction(type.name + ' load3', function() {
+    testLoad(type, 'load3', 3);
+  });
+});
diff --git a/test/built-ins/Simd/logical_operators.js b/test/built-ins/Simd/logical_operators.js
new file mode 100644
index 0000000000..4bc892f725
--- /dev/null
+++ b/test/built-ins/Simd/logical_operators.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: constructor-properties
+description: Test SIMD Logical operations.
+includes: [simdUtilities.js]
+---*/
+
+simdTypes.filter(isLogical).forEach(function(type) {
+  testSimdFunction(type.name + ' and', function() {
+    testBinaryOp(type, 'and', function(a, b) { return a & b; });
+  });
+  testSimdFunction(type.name + ' or', function() {
+    testBinaryOp(type, 'or', function(a, b) { return a | b; });
+  });
+  testSimdFunction(type.name + ' xor', function() {
+    testBinaryOp(type, 'xor', function(a, b) { return a ^ b; });
+  });
+});
diff --git a/test/built-ins/Simd/negate.js b/test/built-ins/Simd/negate.js
new file mode 100644
index 0000000000..7ee9f24d16
--- /dev/null
+++ b/test/built-ins/Simd/negate.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-neg
+description: Tests the unary '-' operation.
+includes: [simdUtilities.js]
+---*/
+
+simdTypes.filter(isNumerical).forEach(function(type) {
+  testSimdFunction(type.name + ' neg', function() {
+    testUnaryOp(type, 'neg', function(a) { return -a; });
+  });
+});
diff --git a/test/built-ins/Simd/not.js b/test/built-ins/Simd/not.js
new file mode 100644
index 0000000000..08f645ec1e
--- /dev/null
+++ b/test/built-ins/Simd/not.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-not
+description: Tests the unary not operation.
+includes: [simdUtilities.js]
+---*/
+
+simdTypes.filter(isIntType).forEach(function(type) {
+  testSimdFunction(type.name + ' not', function() {
+    testUnaryOp(type, 'not', function(a) { return ~a; });
+  });
+});
+
+simdTypes.filter(isBoolType).forEach(function(type) {
+  testSimdFunction(type.name + ' not', function() {
+    testUnaryOp(type, 'not', function(a) { return !a; });
+  });
+});
diff --git a/test/built-ins/Simd/numerical_operators.js b/test/built-ins/Simd/numerical_operators.js
new file mode 100644
index 0000000000..ea032661e6
--- /dev/null
+++ b/test/built-ins/Simd/numerical_operators.js
@@ -0,0 +1,40 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: constructor-properties
+description: Tests the SIMD numerical operations.
+includes: [simdUtilities.js]
+---*/
+
+simdTypes.filter(isNumerical).forEach(function(type) {
+  testSimdFunction(type.name + ' equal', function() {
+    testRelationalOp(type, 'equal', function(a, b) { return a == b; });
+  });
+  testSimdFunction(type.name + ' notEqual', function() {
+    testRelationalOp(type, 'notEqual', function(a, b) { return a != b; });
+  });
+  testSimdFunction(type.name + ' lessThan', function() {
+    testRelationalOp(type, 'lessThan', function(a, b) { return a < b; });
+  });
+  testSimdFunction(type.name + ' lessThanOrEqual', function() {
+    testRelationalOp(type, 'lessThanOrEqual', function(a, b) {
+      return a <= b;
+    });
+  });
+  testSimdFunction(type.name + ' greaterThan', function() {
+    testRelationalOp(type, 'greaterThan', function(a, b) { return a > b; });
+  });
+  testSimdFunction(type.name + ' greaterThanOrEqual', function() {
+    testRelationalOp(type, 'greaterThanOrEqual', function(a, b) { return a >= b; });
+  });
+  testSimdFunction(type.name + ' add', function() {
+    testBinaryOp(type, 'add', function(a, b) { return a + b; });
+  });
+  testSimdFunction(type.name + ' sub', function() {
+    testBinaryOp(type, 'sub', function(a, b) { return a - b; });
+  });
+  testSimdFunction(type.name + ' mul', function() {
+    testBinaryOp(type, 'mul', type.mulFn);
+  });
+});
diff --git a/test/built-ins/Simd/operators.js b/test/built-ins/Simd/operators.js
new file mode 100644
index 0000000000..f638a5ff9c
--- /dev/null
+++ b/test/built-ins/Simd/operators.js
@@ -0,0 +1,58 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: pending
+description: Test SIMD operators.
+includes: [simdUtilities.js]
+---*/
+
+function testOperators(type) {
+  var inst = createTestValue(type);
+  assert.throws(TypeError, function() { Number(inst) });
+  assert.throws(TypeError, function() { +inst });
+  assert.throws(TypeError, function() { -inst });
+  assert.throws(TypeError, function() { ~inst });
+  assert.throws(TypeError, function() { Math.fround(inst) });
+  assert.throws(TypeError, function() { inst|0} );
+  assert.throws(TypeError, function() { inst&0 });
+  assert.throws(TypeError, function() { inst^0 });
+  assert.throws(TypeError, function() { inst>>>0 });
+  assert.throws(TypeError, function() { inst>>0 });
+  assert.throws(TypeError, function() { inst<<0 });
+  assert.throws(TypeError, function() { (inst + inst) });
+  assert.throws(TypeError, function() { inst - inst });
+  assert.throws(TypeError, function() { inst * inst });
+  assert.throws(TypeError, function() { inst / inst });
+  assert.throws(TypeError, function() { inst % inst });
+  assert.throws(TypeError, function() { inst < inst });
+  assert.throws(TypeError, function() { inst > inst });
+  assert.throws(TypeError, function() { inst <= inst });
+  assert.throws(TypeError, function() { inst >= inst });
+  assert.throws(TypeError, function() { inst(); });
+
+  assert.sameValue(inst[0], undefined);
+  assert.sameValue(inst.a, undefined);
+  assert.sameValue(!inst, false);
+  assert.sameValue(!inst, false);
+  assert.sameValue(inst ? 1 : 2, 1);
+  assert.sameValue(inst ? 1 : 2, 1);
+
+  assert.sameValue('function', typeof inst.toString);
+  assert.sameValue('function', typeof inst.toLocaleString);
+  assert.sameValue(inst.toLocaleString(), simdToLocaleString(type, inst));
+
+  var eval_value = eval(inst.toString());
+  var value = type.fn.check(inst);
+  for(var i = 0; i < type.lanes; i++) {
+    assert.sameValue(type.fn.extractLane(eval_value, i),
+        type.fn.extractLane(value, i));
+  }
+  // TODO: test valueOf?
+}
+
+simdTypes.forEach(function(type) {
+  testSimdFunction(type.name + ' operators', function() {
+    testOperators(type);
+  });
+});
diff --git a/test/built-ins/Simd/replace_lane.js b/test/built-ins/Simd/replace_lane.js
new file mode 100644
index 0000000000..42b72d619d
--- /dev/null
+++ b/test/built-ins/Simd/replace_lane.js
@@ -0,0 +1,40 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-abstract-replace-lane
+description: Tests SIMD ReplaceLane.
+includes: [simdUtilities.js]
+---*/
+
+function testReplaceLane(type) {
+  assert.sameValue('function', typeof type.fn.replaceLane);
+  var a = createTestValue(type);
+  for (var v of type.interestingValues) {
+    var expected = simdConvert(type, v);
+    for (var i = 0; i < type.lanes; i++) {
+      var result = type.fn.replaceLane(a, i, v);
+      checkValue(type, result,
+                 function(index) {
+                   return index == i ? expected : type.fn.extractLane(a, index);
+                 });
+    }
+  }
+
+  function testIndexCheck(index, err) {
+    assert.throws(err, function() { type.fn.replaceLane(a, index, 0); });
+  }
+  testIndexCheck(type.lanes, RangeError);
+  testIndexCheck(13.37, TypeError);
+  testIndexCheck(undefined, TypeError);
+  testIndexCheck({}, TypeError);
+  testIndexCheck('yo', TypeError);
+  testIndexCheck(-1, RangeError);
+  testIndexCheck(128, RangeError);
+}
+
+simdTypes.forEach(function(type) {
+  testSimdFunction(type.name + ' replaceLane', function() {
+    testReplaceLane(type);
+  });
+});
diff --git a/test/built-ins/Simd/round_trip.js b/test/built-ins/Simd/round_trip.js
new file mode 100644
index 0000000000..6c9d56399d
--- /dev/null
+++ b/test/built-ins/Simd/round_trip.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: pending
+description: Test round trip.
+includes: [simdUtilities.js]
+---*/
+
+testSimdFunction('Float32x4 Int32x4 round trip', function() {
+  // NaNs should stay unmodified across bit conversions
+  var m = SIMD.Int32x4(0xFFFFFFFF, 0xFFFF0000, 0x80000000, 0x0);
+  var m2 = SIMD.Int32x4.fromFloat32x4Bits(SIMD.Float32x4.fromInt32x4Bits(m));
+  equalInt32x4(m, m2);
+});
diff --git a/test/built-ins/Simd/saturate.js b/test/built-ins/Simd/saturate.js
new file mode 100644
index 0000000000..534cac40df
--- /dev/null
+++ b/test/built-ins/Simd/saturate.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: saturate
+description: Tests saturate methods.
+includes: [simdUtilities.js]
+---*/
+
+simdTypes.filter(isSmallIntType).forEach(function(type) {
+  function saturate(type, a) {
+    if (a < type.minVal) return type.minVal;
+    if (a > type.maxVal) return type.maxVal;
+    return a;
+  }
+  testSimdFunction(type.name + ' addSaturate', function() {
+    testBinaryOp(type, 'addSaturate', function(a, b) {
+      return saturate(type, a + b);
+    });
+  });
+  testSimdFunction(type.name + ' subSaturate', function() {
+    testBinaryOp(type, 'subSaturate', function(a, b) {
+      return saturate(type, a - b);
+    });
+  });
+});
diff --git a/test/built-ins/Simd/select.js b/test/built-ins/Simd/select.js
new file mode 100644
index 0000000000..74ab793806
--- /dev/null
+++ b/test/built-ins/Simd/select.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-select
+description: Tests SIMD Select.
+includes: [simdUtilities.js]
+---*/
+
+function testSelect(type) {
+  assert.sameValue('function', typeof type.fn.select);
+  // set a and b to values that are different for all numerical types.
+  var av = 1;
+  var bv = 2;
+  var a = type.fn.splat(av);
+  var b = type.fn.splat(bv);
+  // test all selectors with a single 'true' lane.
+  for (var i = 0; i < type.lanes; i++) {
+    var selector = type.boolType.fn();
+    selector = type.boolType.fn.replaceLane(selector, i, true);
+    var result = type.fn.select(selector, a, b);
+    checkValue(type, result, function(index) { return index == i ? av : bv; });
+  }
+}
+
+simdTypes.filter(isNumerical).forEach(function(type) {
+  testSimdFunction(type.name + ' select', function() {
+    testSelect(type);
+  });
+});
diff --git a/test/built-ins/Simd/shift_operator.js b/test/built-ins/Simd/shift_operator.js
new file mode 100644
index 0000000000..5fb9314e9a
--- /dev/null
+++ b/test/built-ins/Simd/shift_operator.js
@@ -0,0 +1,55 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: constructor-properties
+description: Test Shift operations.
+includes: [simdUtilities.js]
+---*/
+
+// Compare shift op's behavior to ref op at each lane.
+function testShiftOp(type, op, refOp) {
+  assert.sameValue('function', typeof type.fn[op]);
+  var zero = type.fn();
+  for (var v of type.interestingValues) {
+    var s = type.laneSize * 8;
+    for (var bits of [-1, 0, 1, 2, s - 1, s, s + 1]) {
+      var expected = simdConvert(type, refOp(simdConvert(type, v), bits));
+      var a = type.fn.splat(v);
+      var result = type.fn[op](a, bits);
+      checkValue(type, result, function(index) { return expected; });
+    }
+  }
+}
+
+simdTypes.filter(isIntType).forEach(function(type) {
+  testSimdFunction(type.name + ' shiftLeftByScalar', function() {
+    function shift(a, bits) {
+      bits &= type.laneSize * 8 - 1;
+      return a << bits;
+    }
+    testShiftOp(type, 'shiftLeftByScalar', shift);
+  });
+});
+
+simdTypes.filter(isSignedIntType).forEach(function(type) {
+  testSimdFunction(type.name + ' shiftRightByScalar', function() {
+    function shift(a, bits) {
+      bits &= type.laneSize * 8 - 1;
+      return a >> bits;
+    }
+    testShiftOp(type, 'shiftRightByScalar', shift);
+  });
+});
+
+simdTypes.filter(isUnsignedIntType).forEach(function(type) {
+  testSimdFunction(type.name + ' shiftRightByScalar', function() {
+    function shift(a, bits) {
+      bits &= type.laneSize * 8 - 1;
+      if (type.laneMask)
+        a &= type.laneMask;
+      return a >>> bits;
+    }
+    testShiftOp(type, 'shiftRightByScalar', shift);
+  });
+});
diff --git a/test/built-ins/Simd/shuffle.js b/test/built-ins/Simd/shuffle.js
new file mode 100644
index 0000000000..5b1b7069db
--- /dev/null
+++ b/test/built-ins/Simd/shuffle.js
@@ -0,0 +1,59 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: shuffle
+description: Tests SIMD shuffle.
+includes: [simdUtilities.js]
+---*/
+
+function testShuffle(type) {
+  assert.sameValue('function', typeof type.fn.shuffle);
+  var indices = [];
+  for (var i = 0; i < type.lanes; i++) indices.push(i);
+
+  var a = type.fn.apply(type.fn, indices);            // 0, 1, 2, 3, 4 ...
+  var b = type.fn.add(a, type.fn.splat(type.lanes));  // lanes, lanes+1 ...
+  // All lanes from a.
+  var result = type.fn.shuffle.apply(type.fn, [a, b].concat(indices));
+  checkValue(type, result, function(index) {
+    return type.fn.extractLane(a, index);
+  });
+  // One lane from b.
+  for (var i = 0; i < type.lanes; i++) {
+    var args = [a, b].concat(indices);
+    args[2 + i] += type.lanes;
+    var result = type.fn.shuffle.apply(type.fn, args);
+    checkValue(type, result, function(index) {
+      var val = index == i ? b : a;
+      return type.fn.extractLane(val, index);
+    });
+  }
+  // All lanes from b.
+  for (var i = 0; i < type.lanes; i++) indices[i] += type.lanes;
+  var result = type.fn.shuffle.apply(type.fn, [a, b].concat(indices));
+  checkValue(type, result, function(index) {
+    return type.fn.extractLane(b, index);
+  });
+
+  function testIndexCheck(index, err) {
+    for (var i = 0; i < type.lanes; i++) {
+      var args = [a, b].concat(indices);
+      args[i + 2] = index;
+      assert.throws(err, function() { type.fn.shuffle.apply(type.fn, args); });
+    }
+  }
+  testIndexCheck(2 * type.lanes, RangeError);
+  testIndexCheck(13.37, TypeError);
+  testIndexCheck(undefined, TypeError);
+  testIndexCheck({}, TypeError);
+  testIndexCheck('yo', TypeError);
+  testIndexCheck(-1, RangeError);
+  testIndexCheck(128, RangeError);
+}
+
+simdTypes.filter(isNumerical).forEach(function(type) {
+  testSimdFunction(type.name + ' shuffle', function() {
+    testShuffle(type);
+  });
+});
diff --git a/test/built-ins/Simd/storen.js b/test/built-ins/Simd/storen.js
new file mode 100644
index 0000000000..6aebfdb073
--- /dev/null
+++ b/test/built-ins/Simd/storen.js
@@ -0,0 +1,86 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: simd-store-in-tarray
+description: Tests Simdstore functions.
+includes: [simdUtilities.js]
+---*/
+
+function testStore(type, name, count) {
+  var storeFn = type.fn[name];
+  assert.sameValue('function', typeof storeFn);
+  var bufLanes = 2 * type.lanes;  // Test all alignments.
+  var bufSize = bufLanes * type.laneSize + 8;  // Extra for over-alignment test.
+  var ab = new ArrayBuffer(bufSize);
+  var buf = new type.view(ab);
+  var a = createTestValue(type); // Value containing 0, 1, 2, 3 ...
+  function checkBuffer(offset) {
+    for (var i = 0; i < count; i++)
+      if (buf[offset + i] != i) return false;
+    return true;
+  }
+  // Test aligned stores.
+  for (var i = 0; i < type.lanes; i++) {
+    assert.sameValue(storeFn(buf, i, a), a);
+    assert(checkBuffer(i));
+  }
+  // Test the 2 over-alignments.
+  var f64 = new Float64Array(ab);
+  var stride = 8 / type.laneSize;
+  for (var i = 0; i < 1; i++) {
+    assert.sameValue(storeFn(f64, i, a), a);
+    assert(checkBuffer(stride * i));
+  }
+  // Test the 7 mis-alignments.
+  var i8 = new Int8Array(ab);
+  for (var misalignment = 1; misalignment < 8; misalignment++) {
+    assert.sameValue(storeFn(i8, misalignment, a), a);
+    // Shift the buffer down by misalignment.
+    for (var i = 0; i < i8.length - misalignment; i++)
+      i8[i] = i8[i + misalignment];
+    assert(checkBuffer(0));
+  }
+
+  //Test index coercions
+  storeFn(buf, "0", a);
+  assert(checkBuffer(0));
+  storeFn(buf, "01", a);
+  assert(checkBuffer(1));
+  storeFn(buf, " -0.0 ", a);
+  assert(checkBuffer(0));
+  storeFn(buf, " +1e0", a);
+  assert(checkBuffer(1));
+  storeFn(buf, false, a);
+  assert(checkBuffer(0));
+  storeFn(buf, true, a);
+  assert(checkBuffer(1));
+  storeFn(buf, null, a);
+  assert(checkBuffer(0));
+
+  function testIndexCheck(buf, index, err) {
+    assert.throws(err, function () { storeFn(buf, index, type.fn()); });
+  }
+  testIndexCheck(buf, -1, RangeError);
+  testIndexCheck(buf, bufSize / type.laneSize - count + 1, RangeError);
+  testIndexCheck(buf.buffer, 1, TypeError);
+  testIndexCheck(buf, "a", RangeError);
+}
+
+simdTypes.filter(isNumerical).forEach(function(type) {
+  testSimdFunction(type.name + ' store', function() {
+    testStore(type, 'store', type.lanes);
+  });
+});
+
+simdTypes.filter(hasLoadStore123).forEach(function(type) {
+  testSimdFunction(type.name + ' store1', function() {
+    testStore(type, 'store1', 1);
+  });
+  testSimdFunction(type.name + ' store1', function() {
+    testStore(type, 'store2', 2);
+  });
+  testSimdFunction(type.name + ' store3', function() {
+    testStore(type, 'store3', 3);
+  });
+});
diff --git a/test/built-ins/Simd/swizzle.js b/test/built-ins/Simd/swizzle.js
new file mode 100644
index 0000000000..e6534cdb98
--- /dev/null
+++ b/test/built-ins/Simd/swizzle.js
@@ -0,0 +1,48 @@
+// Copyright (C) 2016 ecmascript_simd authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: swizzle
+description: Tests Simd swizzle.
+includes: [simdUtilities.js]
+---*/
+
+function testSwizzle(type) {
+  assert.sameValue('function', typeof type.fn.swizzle);
+  var a = createTestValue(type);  // 0, 1, 2, 3, 4, 5, 6, ...
+  var indices = [];
+  // Identity swizzle.
+  for (var i = 0; i < type.lanes; i++) indices.push(i);
+  var result = type.fn.swizzle.apply(type.fn, [a].concat(indices));
+  checkValue(type, result, function(index) {
+    return type.fn.extractLane(a, index);
+  });
+  // Reverse swizzle.
+  indices.reverse();
+  var result = type.fn.swizzle.apply(type.fn, [a].concat(indices));
+  checkValue(type, result, function(index) {
+    return type.fn.extractLane(a, type.lanes - index - 1);
+  });
+
+  function testIndexCheck(index, err) {
+    for (var i = 0; i < type.lanes; i++) {
+      var args = [a].concat(indices);
+      args[i + 1] = index;
+      assert.throws(err, function() { type.fn.swizzle.apply(type.fn, args); });
+    }
+  }
+  // RangeError
+  testIndexCheck(type.lanes, RangeError);
+  testIndexCheck(-1, RangeError);
+  testIndexCheck(128, RangeError);
+  testIndexCheck(13.37, TypeError);
+  testIndexCheck(undefined, TypeError);
+  testIndexCheck({}, TypeError);
+  testIndexCheck('yo', TypeError);
+}
+
+simdTypes.filter(isNumerical).forEach(function(type) {
+  testSimdFunction(type.name + ' swizzle', function() {
+    testSwizzle(type);
+  });
+});
-- 
GitLab