SimdUtils.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeLanguagePch.h"
  6. namespace Js
  7. {
  8. bool IsSimdType(Var aVar)
  9. {
  10. TypeId tid = JavascriptOperators::GetTypeId(aVar); //Depends on contiguous SIMD TypeIds
  11. return (TypeIds_SIMDFloat32x4 <= tid && tid <= TypeIds_SIMDBool8x16) ? true : false;
  12. }
  13. int32 SIMDCheckTypedArrayIndex(ScriptContext* scriptContext, Var index)
  14. {
  15. int32 int32Value;
  16. Assert(index != NULL);
  17. int32Value = SIMDCheckInt32Number(scriptContext, index);
  18. return int32Value;
  19. }
  20. int32 SIMDCheckLaneIndex(ScriptContext* scriptContext, Var lane, const int32 range)
  21. {
  22. int32 int32Value;
  23. Assert(lane != NULL);
  24. int32Value = SIMDCheckInt32Number(scriptContext, lane);
  25. if (int32Value < 0 || int32Value >= range)
  26. {
  27. JavascriptError::ThrowRangeError(scriptContext, JSERR_SimdLaneRangeError);
  28. }
  29. return int32Value;
  30. }
  31. // Is Number with int32 value.
  32. int32 SIMDCheckInt32Number(ScriptContext* scriptContext, Var value)
  33. {
  34. int32 int32Value;
  35. if (JavascriptNumber::Is(value))
  36. {
  37. if (!JavascriptNumber::TryGetInt32Value(JavascriptNumber::GetValue(value), &int32Value))
  38. {
  39. JavascriptError::ThrowRangeError(scriptContext, JSERR_ArgumentOutOfRange);
  40. }
  41. }
  42. else if (TaggedInt::Is(value))
  43. {
  44. int32Value = TaggedInt::ToInt32(value);
  45. }
  46. else
  47. {
  48. return static_cast<int32>(JavascriptConversion::ToNumber(value, scriptContext));
  49. }
  50. return int32Value;
  51. }
  52. #if _M_IX86 || _M_AMD64
  53. SIMDValue FromSimdBits(SIMDValue value)
  54. {
  55. X86SIMDValue x86Result;
  56. X86SIMDValue v = X86SIMDValue::ToX86SIMDValue(value);
  57. _mm_store_ps(x86Result.f32, v.m128_value);
  58. return X86SIMDValue::ToSIMDValue(x86Result);
  59. }
  60. #else
  61. SIMDValue FromSimdBits(SIMDValue value)
  62. {
  63. SIMDValue result;
  64. result.i32[SIMD_X] = value.i32[SIMD_X];
  65. result.i32[SIMD_Y] = value.i32[SIMD_Y];
  66. result.i32[SIMD_Z] = value.i32[SIMD_Z];
  67. result.i32[SIMD_W] = value.i32[SIMD_W];
  68. return result;
  69. }
  70. #endif
  71. template <int laneCount>
  72. SIMDValue SIMD128InnerShuffle(SIMDValue src1, SIMDValue src2, int32 lane0, int32 lane1, int32 lane2, int32 lane3)
  73. {
  74. SIMDValue result;
  75. CompileAssert(laneCount == 4 || laneCount == 2);
  76. if (laneCount == 4)
  77. {
  78. result.i32[SIMD_X] = lane0 < 4 ? src1.i32[lane0] : src2.i32[lane0 - 4];
  79. result.i32[SIMD_Y] = lane1 < 4 ? src1.i32[lane1] : src2.i32[lane1 - 4];
  80. result.i32[SIMD_Z] = lane2 < 4 ? src1.i32[lane2] : src2.i32[lane2 - 4];
  81. result.i32[SIMD_W] = lane3 < 4 ? src1.i32[lane3] : src2.i32[lane3 - 4];
  82. }
  83. else
  84. {
  85. result.f64[SIMD_X] = lane0 < 2 ? src1.f64[lane0] : src2.f64[lane0 - 2];
  86. result.f64[SIMD_Y] = lane1 < 2 ? src1.f64[lane1] : src2.f64[lane1 - 2];
  87. }
  88. return result;
  89. }
  90. template <int laneCount>
  91. SIMDValue SIMD128InnerShuffle(SIMDValue src1, SIMDValue src2, const int32* lanes)
  92. {
  93. SIMDValue result = { 0 };
  94. CompileAssert(laneCount == 16 || laneCount == 8);
  95. Assert(lanes != nullptr);
  96. if (laneCount == 8)
  97. {
  98. for (uint i = 0; i < laneCount; ++i)
  99. {
  100. result.i16[i] = lanes[i] < laneCount ? src1.i16[lanes[i]] : src2.i16[lanes[i] - laneCount];
  101. }
  102. }
  103. else
  104. {
  105. for (uint i = 0; i < laneCount; ++i)
  106. {
  107. result.i8[i] = lanes[i] < laneCount ? src1.i8[lanes[i]] : src2.i8[lanes[i] - laneCount];
  108. }
  109. }
  110. return result;
  111. }
  112. template <class SIMDType, int laneCount>
  113. Var SIMD128SlowShuffle(Var src1, Var src2, Var* lanes, const uint range, ScriptContext* scriptContext)
  114. {
  115. SIMDType *a = SIMDType::FromVar(src1);
  116. SIMDType *b = SIMDType::FromVar(src2);
  117. Assert(a);
  118. Assert(b);
  119. SIMDValue src1Value = a->GetValue();
  120. SIMDValue src2Value = b->GetValue();
  121. SIMDValue result;
  122. int32 laneValue[16] = { 0 };
  123. CompileAssert(laneCount == 16 || laneCount == 8);
  124. for (uint i = 0; i < laneCount; ++i)
  125. {
  126. laneValue[i] = SIMDCheckLaneIndex(scriptContext, lanes[i], range);
  127. }
  128. result = SIMD128InnerShuffle<laneCount>(src1Value, src2Value, laneValue);
  129. return SIMDType::New(&result, scriptContext);
  130. }
  131. template Var SIMD128SlowShuffle<JavascriptSIMDInt8x16, 16>(Var src1, Var src2, Var *lanes, const uint range, ScriptContext* scriptContext);
  132. template Var SIMD128SlowShuffle<JavascriptSIMDInt16x8, 8>(Var src1, Var src2, Var *lanes, const uint range, ScriptContext* scriptContext);
  133. template Var SIMD128SlowShuffle<JavascriptSIMDUint8x16, 16>(Var src1, Var src2, Var *lanes, const uint range, ScriptContext* scriptContext);
  134. template Var SIMD128SlowShuffle<JavascriptSIMDUint16x8, 8>(Var src1, Var src2, Var *lanes, const uint range, ScriptContext* scriptContext);
  135. template <class SIMDType, int laneCount>
  136. Var SIMD128SlowShuffle(Var src1, Var src2, Var lane0, Var lane1, Var lane2, Var lane3, int range, ScriptContext* scriptContext)
  137. {
  138. SIMDType *a = SIMDType::FromVar(src1);
  139. SIMDType *b = SIMDType::FromVar(src2);
  140. Assert(a);
  141. Assert(b);
  142. int32 lane0Value = 0;
  143. int32 lane1Value = 0;
  144. int32 lane2Value = 0;
  145. int32 lane3Value = 0;
  146. SIMDValue src1Value = a->GetValue();
  147. SIMDValue src2Value = b->GetValue();
  148. SIMDValue result;
  149. CompileAssert(laneCount == 4 || laneCount == 2);
  150. if (laneCount == 4)
  151. {
  152. lane0Value = SIMDCheckLaneIndex(scriptContext, lane0, range);
  153. lane1Value = SIMDCheckLaneIndex(scriptContext, lane1, range);
  154. lane2Value = SIMDCheckLaneIndex(scriptContext, lane2, range);
  155. lane3Value = SIMDCheckLaneIndex(scriptContext, lane3, range);
  156. Assert(lane0Value >= 0 && lane0Value < range);
  157. Assert(lane1Value >= 0 && lane1Value < range);
  158. Assert(lane2Value >= 0 && lane2Value < range);
  159. Assert(lane3Value >= 0 && lane3Value < range);
  160. result = SIMD128InnerShuffle<4>(src1Value, src2Value, lane0Value, lane1Value, lane2Value, lane3Value);
  161. }
  162. else
  163. {
  164. lane0Value = SIMDCheckLaneIndex(scriptContext, lane0, range);
  165. lane1Value = SIMDCheckLaneIndex(scriptContext, lane1, range);
  166. Assert(lane0Value >= 0 && lane0Value < range);
  167. Assert(lane1Value >= 0 && lane1Value < range);
  168. result = SIMD128InnerShuffle<2>(src1Value, src2Value, lane0Value, lane1Value, lane2Value, lane3Value);
  169. }
  170. return SIMDType::New(&result, scriptContext);
  171. }
  172. template Var SIMD128SlowShuffle<JavascriptSIMDInt32x4, 4> (Var src1, Var src2, Var lane0, Var lane1, Var lane2, Var lane3, int range, ScriptContext* scriptContext);
  173. template Var SIMD128SlowShuffle<JavascriptSIMDFloat32x4, 4> (Var src1, Var src2, Var lane0, Var lane1, Var lane2, Var lane3, int range, ScriptContext* scriptContext);
  174. template Var SIMD128SlowShuffle<JavascriptSIMDFloat64x2, 2> (Var src1, Var src2, Var lane0, Var lane1, Var lane2, Var lane3, int range, ScriptContext* scriptContext);
  175. template Var SIMD128SlowShuffle<JavascriptSIMDUint32x4, 4>(Var src1, Var src2, Var lane0, Var lane1, Var lane2, Var lane3, int range, ScriptContext* scriptContext);
  176. //Int8x16 LaneAccess
  177. inline int8 SIMD128InnerExtractLaneI16(const SIMDValue& src1, const int32 lane)
  178. {
  179. return src1.i8[lane];
  180. }
  181. inline SIMDValue SIMD128InnerReplaceLaneI16(const SIMDValue& src1, const int32 lane, const int8 value)
  182. {
  183. SIMDValue result = src1;
  184. result.i8[lane] = value;
  185. return result;
  186. }
  187. static inline int8 SIMD128GetLaneValue(JavascriptSIMDInt8x16 *jsVal, const int laneValue)
  188. {
  189. Assert(jsVal);
  190. return SIMD128InnerExtractLaneI16(jsVal->GetValue(), laneValue);
  191. }
  192. static inline SIMDValue SIMD128SetLaneValue(JavascriptSIMDInt8x16 *jsVal, const int laneValue, int8 value)
  193. {
  194. Assert(jsVal);
  195. return SIMD128InnerReplaceLaneI16(jsVal->GetValue(), laneValue, value);
  196. }
  197. //Int16x8 LaneAccess
  198. inline int16 SIMD128InnerExtractLaneI8(const SIMDValue& src1, const int32 lane)
  199. {
  200. return src1.i16[lane];
  201. }
  202. inline SIMDValue SIMD128InnerReplaceLaneI8(const SIMDValue& src1, const int32 lane, const int16 value)
  203. {
  204. SIMDValue result = src1;
  205. result.i16[lane] = value;
  206. return result;
  207. }
  208. static inline int16 SIMD128GetLaneValue(JavascriptSIMDInt16x8 *jsVal, const int laneValue)
  209. {
  210. Assert(jsVal);
  211. return SIMD128InnerExtractLaneI8(jsVal->GetValue(), laneValue);
  212. }
  213. static inline SIMDValue SIMD128SetLaneValue(JavascriptSIMDInt16x8 *jsVal, const int laneValue, int16 value)
  214. {
  215. Assert(jsVal);
  216. return SIMD128InnerReplaceLaneI8(jsVal->GetValue(), laneValue, value);
  217. }
  218. //Int32x4 LaneAccess
  219. inline int SIMD128InnerExtractLaneI4(const SIMDValue& src1, const int32 lane)
  220. {
  221. return src1.i32[lane];
  222. }
  223. inline SIMDValue SIMD128InnerReplaceLaneI4(const SIMDValue& src1, const int32 lane, const int value)
  224. {
  225. SIMDValue result = src1;
  226. result.i32[lane] = value;
  227. return result;
  228. }
  229. static inline int SIMD128GetLaneValue(JavascriptSIMDInt32x4 *jsVal, const int laneValue)
  230. {
  231. Assert(jsVal);
  232. return SIMD128InnerExtractLaneI4(jsVal->GetValue(), laneValue);
  233. }
  234. static inline SIMDValue SIMD128SetLaneValue(JavascriptSIMDInt32x4 *jsVal, const int laneValue, int value)
  235. {
  236. Assert(jsVal);
  237. return SIMD128InnerReplaceLaneI4(jsVal->GetValue(), laneValue, value);
  238. }
  239. //Float32x4 LaneAccess
  240. inline float SIMD128InnerExtractLaneF4(const SIMDValue& src1, const int32 lane)
  241. {
  242. return src1.f32[lane];
  243. }
  244. inline SIMDValue SIMD128InnerReplaceLaneF4(const SIMDValue& src1, const int32 lane, const float value)
  245. {
  246. SIMDValue result = src1;
  247. result.f32[lane] = value;
  248. return result;
  249. }
  250. static inline float SIMD128GetLaneValue(JavascriptSIMDFloat32x4 *jsVal, const int laneValue)
  251. {
  252. Assert(jsVal);
  253. return SIMD128InnerExtractLaneF4(jsVal->GetValue(), laneValue);
  254. }
  255. static inline SIMDValue SIMD128SetLaneValue(JavascriptSIMDFloat32x4 *jsVal, const int laneValue, float value)
  256. {
  257. Assert(jsVal);
  258. return SIMD128InnerReplaceLaneF4(jsVal->GetValue(), laneValue, value);
  259. }
  260. //Bool32x4 LaneAccess
  261. static inline bool SIMD128GetLaneValue(JavascriptSIMDBool32x4 *jsVal, const int laneValue)
  262. {
  263. Assert(jsVal);
  264. return SIMD128InnerExtractLaneI4(jsVal->GetValue(), laneValue) == -1;
  265. }
  266. static inline SIMDValue SIMD128SetLaneValue(JavascriptSIMDBool32x4 *jsVal, const int laneValue, bool value)
  267. {
  268. Assert(jsVal);
  269. return SIMD128InnerReplaceLaneI4(jsVal->GetValue(), laneValue, value ? -1 : 0);
  270. }
  271. //Bool16x8 LaneAccess
  272. static inline bool SIMD128GetLaneValue(JavascriptSIMDBool16x8 *jsVal, const int laneValue)
  273. {
  274. Assert(jsVal);
  275. return SIMD128InnerExtractLaneI8(jsVal->GetValue(), laneValue) == -1;
  276. }
  277. static inline SIMDValue SIMD128SetLaneValue(JavascriptSIMDBool16x8 *jsVal, const int laneValue, bool value)
  278. {
  279. Assert(jsVal);
  280. return SIMD128InnerReplaceLaneI8(jsVal->GetValue(), laneValue, value ? -1 : 0);
  281. }
  282. //Bool8x16 LaneAccess
  283. static inline bool SIMD128GetLaneValue(JavascriptSIMDBool8x16 *jsVal, const int laneValue)
  284. {
  285. Assert(jsVal);
  286. return SIMD128InnerExtractLaneI16(jsVal->GetValue(), laneValue) == -1;
  287. }
  288. static inline SIMDValue SIMD128SetLaneValue(JavascriptSIMDBool8x16 *jsVal, const int laneValue, bool value)
  289. {
  290. Assert(jsVal);
  291. return SIMD128InnerReplaceLaneI16(jsVal->GetValue(), laneValue, value ? -1 : 0);
  292. }
  293. //Uint32x4 Lane Access
  294. static inline uint SIMD128GetLaneValue(JavascriptSIMDUint32x4 *jsVal, const int laneValue)
  295. {
  296. Assert(jsVal);
  297. return (uint) SIMD128InnerExtractLaneI4(jsVal->GetValue(), laneValue);
  298. }
  299. static inline SIMDValue SIMD128SetLaneValue(JavascriptSIMDUint32x4 *jsVal, const int laneValue, uint value)
  300. {
  301. Assert(jsVal);
  302. return SIMD128InnerReplaceLaneI4(jsVal->GetValue(), laneValue, value);
  303. }
  304. //Uint8x16 LaneAccess
  305. static inline uint8 SIMD128GetLaneValue(JavascriptSIMDUint8x16 *jsVal, const int laneValue)
  306. {
  307. Assert(jsVal);
  308. return (uint8) SIMD128InnerExtractLaneI16(jsVal->GetValue(), laneValue);
  309. }
  310. static inline SIMDValue SIMD128SetLaneValue(JavascriptSIMDUint8x16 *jsVal, const int laneValue, uint8 value)
  311. {
  312. Assert(jsVal);
  313. return SIMD128InnerReplaceLaneI16(jsVal->GetValue(), laneValue, value);
  314. }
  315. //Uint16x8 LaneAccess
  316. static inline uint16 SIMD128GetLaneValue(JavascriptSIMDUint16x8 *jsVal, const int laneValue)
  317. {
  318. Assert(jsVal);
  319. return (uint16) SIMD128InnerExtractLaneI8(jsVal->GetValue(), laneValue);
  320. }
  321. static inline SIMDValue SIMD128SetLaneValue(JavascriptSIMDUint16x8 *jsVal, const int laneValue, uint16 value)
  322. {
  323. Assert(jsVal);
  324. return SIMD128InnerReplaceLaneI8(jsVal->GetValue(), laneValue, value);
  325. }
  326. template<class SIMDType, int laneCount, typename T>
  327. inline T SIMD128ExtractLane(const Var src, const Var lane, ScriptContext* scriptContext)
  328. {
  329. SIMDType *jsVal = SIMDType::FromVar(src);
  330. Assert(jsVal);
  331. int32 laneValue = SIMDCheckLaneIndex(scriptContext, lane, laneCount);
  332. Assert(laneValue >= 0 && laneValue < laneCount);
  333. return SIMD128GetLaneValue(jsVal, laneValue);
  334. }
  335. template<class SIMDType, int laneCount, typename T>
  336. inline SIMDValue SIMD128ReplaceLane(const Var src, const Var lane, const T value, ScriptContext* scriptContext)
  337. {
  338. SIMDType *jsVal = SIMDType::FromVar(src);
  339. Assert(jsVal);
  340. int32 laneValue = SIMDCheckLaneIndex(scriptContext, lane, laneCount);
  341. Assert(laneValue >= 0 && laneValue < laneCount);
  342. return SIMD128SetLaneValue(jsVal, laneValue, value);
  343. }
  344. template int8 SIMD128ExtractLane<JavascriptSIMDInt8x16, 16, int8>(Var src, Var lane, ScriptContext* scriptContext);
  345. template SIMDValue SIMD128ReplaceLane<JavascriptSIMDInt8x16, 16, int8>(Var src, Var lane, int8 value, ScriptContext* scriptContext);
  346. template int16 SIMD128ExtractLane<JavascriptSIMDInt16x8, 8, int16>(Var src, Var lane, ScriptContext* scriptContext);
  347. template SIMDValue SIMD128ReplaceLane<JavascriptSIMDInt16x8, 8, int16>(Var src, Var lane, int16 value, ScriptContext* scriptContext);
  348. template int SIMD128ExtractLane<JavascriptSIMDInt32x4, 4, int>(Var src, Var lane, ScriptContext* scriptContext);
  349. template SIMDValue SIMD128ReplaceLane<JavascriptSIMDInt32x4, 4, int>(Var src, Var lane, int value, ScriptContext* scriptContext);
  350. template float SIMD128ExtractLane<JavascriptSIMDFloat32x4, 4, float>(Var src, Var lane, ScriptContext* scriptContext);
  351. template SIMDValue SIMD128ReplaceLane<JavascriptSIMDFloat32x4, 4, float>(Var src, Var lane, float value, ScriptContext* scriptContext);
  352. template bool SIMD128ExtractLane<JavascriptSIMDBool32x4, 4, bool>(Var src, Var lane, ScriptContext* scriptContext);
  353. template SIMDValue SIMD128ReplaceLane<JavascriptSIMDBool32x4, 4, bool>(Var src, Var lane, bool value, ScriptContext* scriptContext);
  354. template bool SIMD128ExtractLane<JavascriptSIMDBool16x8, 8, bool>(Var src, Var lane, ScriptContext* scriptContext);
  355. template SIMDValue SIMD128ReplaceLane<JavascriptSIMDBool16x8, 8, bool>(Var src, Var lane, bool value, ScriptContext* scriptContext);
  356. template bool SIMD128ExtractLane<JavascriptSIMDBool8x16, 16, bool>(Var src, Var lane, ScriptContext* scriptContext);
  357. template SIMDValue SIMD128ReplaceLane<JavascriptSIMDBool8x16, 16, bool>(Var src, Var lane, bool value, ScriptContext* scriptContext);
  358. template uint SIMD128ExtractLane<JavascriptSIMDUint32x4, 4, uint>(Var src, Var lane, ScriptContext* scriptContext);
  359. template SIMDValue SIMD128ReplaceLane<JavascriptSIMDUint32x4, 4, uint>(Var src, Var lane, uint value, ScriptContext* scriptContext);
  360. template uint8 SIMD128ExtractLane<JavascriptSIMDUint8x16, 16, uint8>(Var src, Var lane, ScriptContext* scriptContext);
  361. template SIMDValue SIMD128ReplaceLane<JavascriptSIMDUint8x16, 16, uint8>(Var src, Var lane, uint8 value, ScriptContext* scriptContext);
  362. template uint16 SIMD128ExtractLane<JavascriptSIMDUint16x8, 8, uint16>(Var src, Var lane, ScriptContext* scriptContext);
  363. template SIMDValue SIMD128ReplaceLane<JavascriptSIMDUint16x8, 8, uint16>(Var src, Var lane, uint16 value, ScriptContext* scriptContext);
  364. bool SIMDIsSupportedTypedArray(Var value)
  365. {
  366. return JavascriptOperators::GetTypeId(value) >= TypeIds_Int8Array && JavascriptOperators::GetTypeId(value) <= TypeIds_Float64Array;
  367. }
  368. /*
  369. Checks if:
  370. 1. Array is supported typed array
  371. 2. Lane index is a Number/TaggedInt and int32 value
  372. 3. Lane index is within array bounds
  373. */
  374. SIMDValue* SIMDCheckTypedArrayAccess(Var arg1, Var arg2, TypedArrayBase **tarray, int32 *index, uint32 dataWidth, ScriptContext *scriptContext)
  375. {
  376. if (!SIMDIsSupportedTypedArray(arg1))
  377. {
  378. JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdInvalidArgType, L"Simd typed array access");
  379. }
  380. *index = SIMDCheckInt32Number(scriptContext, arg2);
  381. // bound check
  382. *tarray = TypedArrayBase::FromVar(arg1);
  383. uint32 bpe = (*tarray)->GetBytesPerElement();
  384. int32 offset = (*index) * bpe;
  385. if (offset < 0 || (offset + dataWidth) >(int32)(*tarray)->GetByteLength())
  386. {
  387. JavascriptError::ThrowRangeError(scriptContext, JSERR_ArgumentOutOfRange, L"Simd typed array access");
  388. }
  389. return (SIMDValue*)((*tarray)->GetByteBuffer() + offset);
  390. }
  391. SIMDValue SIMDLdData(SIMDValue *data, uint8 dataWidth)
  392. {
  393. SIMDValue result = { 0, 0, 0, 0 };
  394. // bitwise copy. Always use integer fields to avoid wrong copy of NaNs.
  395. switch (dataWidth)
  396. {
  397. case 16:
  398. result.i32[SIMD_W] = data->i32[SIMD_W];
  399. // fall through
  400. case 12:
  401. result.i32[SIMD_Z] = data->i32[SIMD_Z];
  402. // fall through
  403. case 8:
  404. result.i32[SIMD_Y] = data->i32[SIMD_Y];
  405. // fall through
  406. case 4:
  407. result.i32[SIMD_X] = data->i32[SIMD_X];
  408. break;
  409. default:
  410. Assert(UNREACHED);
  411. }
  412. return result;
  413. }
  414. void SIMDStData(SIMDValue *data, SIMDValue simdValue, uint8 dataWidth)
  415. {
  416. // bitwise copy. Always use integer fields to avoid wrong copy of NaNs.
  417. switch (dataWidth)
  418. {
  419. case 16:
  420. data->i32[SIMD_W] = simdValue.i32[SIMD_W];
  421. // fall through
  422. case 12:
  423. data->i32[SIMD_Z] = simdValue.i32[SIMD_Z];
  424. // fall through
  425. case 8:
  426. data->i32[SIMD_Y] = simdValue.i32[SIMD_Y];
  427. // fall through
  428. case 4:
  429. data->i32[SIMD_X] = simdValue.i32[SIMD_X];
  430. break;
  431. default:
  432. Assert(UNREACHED);
  433. }
  434. }
  435. #if ENABLE_NATIVE_CODEGEN
  436. // Maps Simd opcodes which are non-contiguous to a zero-based linear space. Used to index a table using a Simd opcode.
  437. uint32 SimdOpcodeAsIndex(Js::OpCode op)
  438. {
  439. if (op <= Js::OpCode::Simd128_End)
  440. {
  441. return (uint32)((Js::OpCode)op - Js::OpCode::Simd128_Start);
  442. }
  443. else
  444. {
  445. Assert(op >= Js::OpCode::Simd128_Start_Extend && op <= Js::OpCode::Simd128_End_Extend);
  446. return (uint32)((Js::OpCode)op - Js::OpCode::Simd128_Start_Extend) + (uint32)(Js::OpCode::Simd128_End - Js::OpCode::Simd128_Start) + 1;
  447. }
  448. }
  449. #endif
  450. }