michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef builtin_SIMD_h michael@0: #define builtin_SIMD_h michael@0: michael@0: #include "jsapi.h" michael@0: #include "jsobj.h" michael@0: #include "builtin/TypedObject.h" michael@0: #include "vm/GlobalObject.h" michael@0: michael@0: /* michael@0: * JS SIMD functions. michael@0: * Spec matching polyfill: michael@0: * https://github.com/johnmccutchan/ecmascript_simd/blob/master/src/ecmascript_simd.js michael@0: */ michael@0: michael@0: #define FLOAT32X4_NULLARY_FUNCTION_LIST(V) \ michael@0: V(zero, (FuncZero), 0, 0, Zero) michael@0: michael@0: #define FLOAT32X4_UNARY_FUNCTION_LIST(V) \ michael@0: V(abs, (Func, Float32x4>), 1, 0, Abs) \ michael@0: V(bitsToInt32x4, (FuncConvertBits), 1, 0, BitsToInt32x4) \ michael@0: V(neg, (Func, Float32x4>), 1, 0, Neg) \ michael@0: V(reciprocal, (Func, Float32x4>), 1, 0, Reciprocal) \ michael@0: V(reciprocalSqrt, (Func, Float32x4>), 1, 0, ReciprocalSqrt) \ michael@0: V(splat, (FuncSplat), 1, 0, Splat) \ michael@0: V(sqrt, (Func, Float32x4>), 1, 0, Sqrt) \ michael@0: V(toInt32x4, (FuncConvert), 1, 0, ToInt32x4) michael@0: michael@0: #define FLOAT32X4_BINARY_FUNCTION_LIST(V) \ michael@0: V(add, (Func, Float32x4>), 2, 0, Add) \ michael@0: V(div, (Func, Float32x4>), 2, 0, Div) \ michael@0: V(equal, (Func, Int32x4>), 2, 0, Equal) \ michael@0: V(greaterThan, (Func, Int32x4>), 2, 0, GreaterThan) \ michael@0: V(greaterThanOrEqual, (Func, Int32x4>), 2, 0, GreaterThanOrEqual) \ michael@0: V(lessThan, (Func, Int32x4>), 2, 0, LessThan) \ michael@0: V(lessThanOrEqual, (Func, Int32x4>), 2, 0, LessThanOrEqual) \ michael@0: V(max, (Func, Float32x4>), 2, 0, Max) \ michael@0: V(min, (Func, Float32x4>), 2, 0, Min) \ michael@0: V(mul, (Func, Float32x4>), 2, 0, Mul) \ michael@0: V(notEqual, (Func, Int32x4>), 2, 0, NotEqual) \ michael@0: V(shuffle, (FuncShuffle, Float32x4>), 2, 0, Shuffle) \ michael@0: V(scale, (FuncWith, Float32x4>), 2, 0, Scale) \ michael@0: V(sub, (Func, Float32x4>), 2, 0, Sub) \ michael@0: V(withX, (FuncWith, Float32x4>), 2, 0, WithX) \ michael@0: V(withY, (FuncWith, Float32x4>), 2, 0, WithY) \ michael@0: V(withZ, (FuncWith, Float32x4>), 2, 0, WithZ) \ michael@0: V(withW, (FuncWith, Float32x4>), 2, 0, WithW) michael@0: michael@0: #define FLOAT32X4_TERNARY_FUNCTION_LIST(V) \ michael@0: V(clamp, Float32x4Clamp, 3, 0, Clamp) \ michael@0: V(shuffleMix, (FuncShuffle, Float32x4>), 3, 0, ShuffleMix) michael@0: michael@0: #define FLOAT32X4_FUNCTION_LIST(V) \ michael@0: FLOAT32X4_NULLARY_FUNCTION_LIST(V) \ michael@0: FLOAT32X4_UNARY_FUNCTION_LIST(V) \ michael@0: FLOAT32X4_BINARY_FUNCTION_LIST(V) \ michael@0: FLOAT32X4_TERNARY_FUNCTION_LIST(V) michael@0: michael@0: #define INT32X4_NULLARY_FUNCTION_LIST(V) \ michael@0: V(zero, (FuncZero), 0, 0, Zero) michael@0: michael@0: #define INT32X4_UNARY_FUNCTION_LIST(V) \ michael@0: V(bitsToFloat32x4, (FuncConvertBits), 1, 0, BitsToFloat32x4) \ michael@0: V(neg, (Func, Int32x4>), 1, 0, Neg) \ michael@0: V(not, (Func, Int32x4>), 1, 0, Not) \ michael@0: V(splat, (FuncSplat), 0, 0, Splat) \ michael@0: V(toFloat32x4, (FuncConvert), 1, 0, ToFloat32x4) michael@0: michael@0: #define INT32X4_BINARY_FUNCTION_LIST(V) \ michael@0: V(add, (Func, Int32x4>), 2, 0, Add) \ michael@0: V(and, (Func, Int32x4>), 2, 0, And) \ michael@0: V(mul, (Func, Int32x4>), 2, 0, Mul) \ michael@0: V(or, (Func, Int32x4>), 2, 0, Or) \ michael@0: V(sub, (Func, Int32x4>), 2, 0, Sub) \ michael@0: V(shuffle, (FuncShuffle, Int32x4>), 2, 0, Shuffle) \ michael@0: V(withFlagX, (FuncWith, Int32x4>), 2, 0, WithFlagX) \ michael@0: V(withFlagY, (FuncWith, Int32x4>), 2, 0, WithFlagY) \ michael@0: V(withFlagZ, (FuncWith, Int32x4>), 2, 0, WithFlagZ) \ michael@0: V(withFlagW, (FuncWith, Int32x4>), 2, 0, WithFlagW) \ michael@0: V(withX, (FuncWith, Int32x4>), 2, 0, WithX) \ michael@0: V(withY, (FuncWith, Int32x4>), 2, 0, WithY) \ michael@0: V(withZ, (FuncWith, Int32x4>), 2, 0, WithZ) \ michael@0: V(withW, (FuncWith, Int32x4>), 2, 0, WithW) \ michael@0: V(xor, (Func, Int32x4>), 2, 0, Xor) michael@0: michael@0: #define INT32X4_TERNARY_FUNCTION_LIST(V) \ michael@0: V(select, Int32x4Select, 3, 0, Select) \ michael@0: V(shuffleMix, (FuncShuffle, Int32x4>), 3, 0, ShuffleMix) michael@0: michael@0: #define INT32X4_QUARTERNARY_FUNCTION_LIST(V) \ michael@0: V(bool, Int32x4Bool, 4, 0, Bool) michael@0: michael@0: #define INT32X4_FUNCTION_LIST(V) \ michael@0: INT32X4_NULLARY_FUNCTION_LIST(V) \ michael@0: INT32X4_UNARY_FUNCTION_LIST(V) \ michael@0: INT32X4_BINARY_FUNCTION_LIST(V) \ michael@0: INT32X4_TERNARY_FUNCTION_LIST(V) \ michael@0: INT32X4_QUARTERNARY_FUNCTION_LIST(V) michael@0: michael@0: namespace js { michael@0: michael@0: class SIMDObject : public JSObject michael@0: { michael@0: public: michael@0: static const Class class_; michael@0: static JSObject* initClass(JSContext *cx, Handle global); michael@0: static bool toString(JSContext *cx, unsigned int argc, jsval *vp); michael@0: }; michael@0: michael@0: // These classes exist for use with templates below. michael@0: michael@0: struct Float32x4 { michael@0: typedef float Elem; michael@0: static const int32_t lanes = 4; michael@0: static const X4TypeDescr::Type type = X4TypeDescr::TYPE_FLOAT32; michael@0: michael@0: static TypeDescr &GetTypeDescr(GlobalObject &global) { michael@0: return global.float32x4TypeDescr().as(); michael@0: } michael@0: static Elem toType(Elem a) { michael@0: return a; michael@0: } michael@0: static bool toType(JSContext *cx, JS::HandleValue v, Elem *out) { michael@0: *out = v.toNumber(); michael@0: return true; michael@0: } michael@0: static void setReturn(CallArgs &args, Elem value) { michael@0: args.rval().setDouble(JS::CanonicalizeNaN(value)); michael@0: } michael@0: }; michael@0: michael@0: struct Int32x4 { michael@0: typedef int32_t Elem; michael@0: static const int32_t lanes = 4; michael@0: static const X4TypeDescr::Type type = X4TypeDescr::TYPE_INT32; michael@0: michael@0: static TypeDescr &GetTypeDescr(GlobalObject &global) { michael@0: return global.int32x4TypeDescr().as(); michael@0: } michael@0: static Elem toType(Elem a) { michael@0: return ToInt32(a); michael@0: } michael@0: static bool toType(JSContext *cx, JS::HandleValue v, Elem *out) { michael@0: return ToInt32(cx, v, out); michael@0: } michael@0: static void setReturn(CallArgs &args, Elem value) { michael@0: args.rval().setInt32(value); michael@0: } michael@0: }; michael@0: michael@0: template michael@0: JSObject *Create(JSContext *cx, typename V::Elem *data); michael@0: michael@0: #define DECLARE_SIMD_FLOAT32X4_FUNCTION(Name, Func, Operands, Flags, MIRId) \ michael@0: extern bool \ michael@0: simd_float32x4_##Name(JSContext *cx, unsigned argc, Value *vp); michael@0: FLOAT32X4_FUNCTION_LIST(DECLARE_SIMD_FLOAT32X4_FUNCTION) michael@0: #undef DECLARE_SIMD_FLOAT32X4_FUNCTION michael@0: michael@0: #define DECLARE_SIMD_INT32x4_FUNCTION(Name, Func, Operands, Flags, MIRId) \ michael@0: extern bool \ michael@0: simd_int32x4_##Name(JSContext *cx, unsigned argc, Value *vp); michael@0: INT32X4_FUNCTION_LIST(DECLARE_SIMD_INT32x4_FUNCTION) michael@0: #undef DECLARE_SIMD_INT32x4_FUNCTION michael@0: michael@0: } /* namespace js */ michael@0: michael@0: JSObject * michael@0: js_InitSIMDClass(JSContext *cx, js::HandleObject obj); michael@0: michael@0: #endif /* builtin_SIMD_h */