wasm.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Copyright (c), Recep Aslantas.
  3. *
  4. * MIT License (MIT), http://opensource.org/licenses/MIT
  5. * Full license can be found in the LICENSE file
  6. */
  7. #ifndef cglm_simd_wasm_h
  8. #define cglm_simd_wasm_h
  9. #include "intrin.h"
  10. #ifdef CGLM_SIMD_WASM
  11. #include <wasm_simd128.h>
  12. #define glmm_load(p) wasm_v128_load(p)
  13. #define glmm_store(p, a) wasm_v128_store(p, (a))
  14. #define glmm_set1(x) wasm_f32x4_splat(x)
  15. #define glmm_set1_rval(x) wasm_f32x4_splat(x)
  16. #define glmm_128 v128_t
  17. #define glmm_shuff1(xmm, z, y, x, w) wasm_i32x4_shuffle(xmm, xmm, w, x, y, z)
  18. #define glmm_splat(x, lane) glmm_shuff1(x, lane, lane, lane, lane)
  19. #define glmm_splat_x(x) glmm_splat(x, 0)
  20. #define glmm_splat_y(x) glmm_splat(x, 1)
  21. #define glmm_splat_z(x) glmm_splat(x, 2)
  22. #define glmm_splat_w(x) glmm_splat(x, 3)
  23. #define GLMM_NEGZEROf 0x80000000 /* 0x80000000 ---> -0.0f */
  24. /* _mm_set_ps(X, Y, Z, W); */
  25. #define GLMM__SIGNMASKf(X, Y, Z, W) wasm_i32x4_const(X, Y, Z, W)
  26. #define glmm_float32x4_SIGNMASK_PNPN GLMM__SIGNMASKf(0, GLMM_NEGZEROf, 0, GLMM_NEGZEROf)
  27. #define glmm_float32x4_SIGNMASK_NPNP GLMM__SIGNMASKf(GLMM_NEGZEROf, 0, GLMM_NEGZEROf, 0)
  28. #define glmm_float32x4_SIGNMASK_NPPN GLMM__SIGNMASKf(GLMM_NEGZEROf, 0, 0, GLMM_NEGZEROf)
  29. #define glmm_float32x4_SIGNMASK_NEG wasm_i32x4_const_splat(GLMM_NEGZEROf)
  30. static inline glmm_128 glmm_abs(glmm_128 x) { return wasm_f32x4_abs(x); }
  31. static inline glmm_128 glmm_min(glmm_128 a, glmm_128 b) { return wasm_f32x4_pmin(b, a); }
  32. static inline glmm_128 glmm_max(glmm_128 a, glmm_128 b) { return wasm_f32x4_pmax(b, a); }
  33. static inline
  34. glmm_128
  35. glmm_vhadd(glmm_128 v) {
  36. glmm_128 x0;
  37. x0 = wasm_f32x4_add(v, glmm_shuff1(v, 0, 1, 2, 3));
  38. x0 = wasm_f32x4_add(x0, glmm_shuff1(x0, 1, 0, 0, 1));
  39. return x0;
  40. }
  41. static inline
  42. glmm_128
  43. glmm_vhadds(glmm_128 v) {
  44. glmm_128 shuf, sums;
  45. shuf = glmm_shuff1(v, 2, 3, 0, 1);
  46. sums = wasm_f32x4_add(v, shuf);
  47. /* shuf = _mm_movehl_ps(shuf, sums); */
  48. shuf = wasm_i32x4_shuffle(shuf, sums, 6, 7, 2, 3);
  49. sums = wasm_i32x4_shuffle(sums, wasm_f32x4_add(sums, shuf), 4, 1, 2, 3);
  50. return sums;
  51. }
  52. static inline
  53. float
  54. glmm_hadd(glmm_128 v) {
  55. return wasm_f32x4_extract_lane(glmm_vhadds(v), 0);
  56. }
  57. static inline
  58. glmm_128
  59. glmm_vhmin(glmm_128 v) {
  60. glmm_128 x0, x1, x2;
  61. x0 = glmm_shuff1(v, 2, 3, 2, 3); /* [2, 3, 2, 3] */
  62. x1 = wasm_f32x4_pmin(x0, v); /* [0|2, 1|3, 2|2, 3|3] */
  63. x2 = glmm_splat(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */
  64. return wasm_f32x4_pmin(x1, x2);
  65. }
  66. static inline
  67. float
  68. glmm_hmin(glmm_128 v) {
  69. return wasm_f32x4_extract_lane(glmm_vhmin(v), 0);
  70. }
  71. static inline
  72. glmm_128
  73. glmm_vhmax(glmm_128 v) {
  74. glmm_128 x0, x1, x2;
  75. x0 = glmm_shuff1(v, 2, 3, 2, 3); /* [2, 3, 2, 3] */
  76. x1 = wasm_f32x4_pmax(x0, v); /* [0|2, 1|3, 2|2, 3|3] */
  77. x2 = glmm_splat(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */
  78. /* _mm_max_ss */
  79. return wasm_i32x4_shuffle(x1, wasm_f32x4_pmax(x1, x2), 4, 1, 2, 3);
  80. }
  81. static inline
  82. float
  83. glmm_hmax(glmm_128 v) {
  84. return wasm_f32x4_extract_lane(glmm_vhmax(v), 0);
  85. }
  86. static inline
  87. glmm_128
  88. glmm_vdots(glmm_128 a, glmm_128 b) {
  89. return glmm_vhadds(wasm_f32x4_mul(a, b));
  90. }
  91. static inline
  92. glmm_128
  93. glmm_vdot(glmm_128 a, glmm_128 b) {
  94. glmm_128 x0;
  95. x0 = wasm_f32x4_mul(a, b);
  96. x0 = wasm_f32x4_add(x0, glmm_shuff1(x0, 1, 0, 3, 2));
  97. return wasm_f32x4_add(x0, glmm_shuff1(x0, 0, 1, 0, 1));
  98. }
  99. static inline
  100. float
  101. glmm_dot(glmm_128 a, glmm_128 b) {
  102. return wasm_f32x4_extract_lane(glmm_vdots(a, b), 0);
  103. }
  104. static inline
  105. float
  106. glmm_norm(glmm_128 a) {
  107. glmm_128 x0;
  108. x0 = glmm_vhadds(wasm_f32x4_mul(a, a));
  109. return wasm_f32x4_extract_lane(
  110. wasm_i32x4_shuffle(x0, wasm_f32x4_sqrt(x0),4, 1, 2, 3), 0);
  111. }
  112. static inline
  113. float
  114. glmm_norm2(glmm_128 a) {
  115. return wasm_f32x4_extract_lane(glmm_vhadds(wasm_f32x4_mul(a, a)), 0);
  116. }
  117. static inline
  118. float
  119. glmm_norm_one(glmm_128 a) {
  120. return wasm_f32x4_extract_lane(glmm_vhadds(glmm_abs(a)), 0);
  121. }
  122. static inline
  123. float
  124. glmm_norm_inf(glmm_128 a) {
  125. return wasm_f32x4_extract_lane(glmm_vhmax(glmm_abs(a)), 0);
  126. }
  127. static inline
  128. glmm_128
  129. glmm_load3(float v[3]) {
  130. glmm_128 xy = wasm_v128_load64_zero(v);
  131. return wasm_f32x4_replace_lane(xy, 2, v[2]);
  132. }
  133. static inline
  134. void
  135. glmm_store3(float v[3], glmm_128 vx) {
  136. wasm_v128_store64_lane(v, vx, 0);
  137. wasm_v128_store32_lane(&v[2], vx, 2);
  138. }
  139. static inline
  140. glmm_128
  141. glmm_div(glmm_128 a, glmm_128 b) {
  142. return wasm_f32x4_div(a, b);
  143. }
  144. static inline
  145. glmm_128
  146. glmm_fmadd(glmm_128 a, glmm_128 b, glmm_128 c) {
  147. return wasm_f32x4_add(c, wasm_f32x4_mul(a, b));
  148. }
  149. static inline
  150. glmm_128
  151. glmm_fnmadd(glmm_128 a, glmm_128 b, glmm_128 c) {
  152. return wasm_f32x4_sub(c, wasm_f32x4_mul(a, b));
  153. }
  154. static inline
  155. glmm_128
  156. glmm_fmsub(glmm_128 a, glmm_128 b, glmm_128 c) {
  157. return wasm_f32x4_sub(wasm_f32x4_mul(a, b), c);
  158. }
  159. static inline
  160. glmm_128
  161. glmm_fnmsub(glmm_128 a, glmm_128 b, glmm_128 c) {
  162. return wasm_f32x4_neg(wasm_f32x4_add(wasm_f32x4_mul(a, b), c));
  163. }
  164. #endif
  165. #endif /* cglm_simd_wasm_h */