MathUtilNeon.inl 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. namespace gameplay
  2. {
  3. inline void MathUtil::addMatrix(const float* m, float scalar, float* dst)
  4. {
  5. asm volatile(
  6. "vld1.32 {q0, q1}, [%1]! \n\t" // M[m0-m7]
  7. "vld1.32 {q2, q3}, [%1] \n\t" // M[m8-m15]
  8. "vld1.32 {d8[0]}, [%2] \n\t" // s
  9. "vmov.f32 s17, s16 \n\t" // s
  10. "vmov.f32 s18, s16 \n\t" // s
  11. "vmov.f32 s19, s16 \n\t" // s
  12. "vadd.f32 q8, q0, q4 \n\t" // DST->M[m0-m3] = M[m0-m3] + s
  13. "vadd.f32 q9, q1, q4 \n\t" // DST->M[m4-m7] = M[m4-m7] + s
  14. "vadd.f32 q10, q2, q4 \n\t" // DST->M[m8-m11] = M[m8-m11] + s
  15. "vadd.f32 q11, q3, q4 \n\t" // DST->M[m12-m15] = M[m12-m15] + s
  16. "vst1.32 {q8, q9}, [%0]! \n\t" // DST->M[m0-m7]
  17. "vst1.32 {q10, q11}, [%0] \n\t" // DST->M[m8-m15]
  18. :
  19. : "r"(dst), "r"(m), "r"(&scalar)
  20. : "q0", "q1", "q2", "q3", "q4", "q8", "q9", "q10", "q11", "memory"
  21. );
  22. }
  23. inline void MathUtil::addMatrix(const float* m1, const float* m2, float* dst)
  24. {
  25. asm volatile(
  26. "vld1.32 {q0, q1}, [%1]! \n\t" // M1[m0-m7]
  27. "vld1.32 {q2, q3}, [%1] \n\t" // M1[m8-m15]
  28. "vld1.32 {q8, q9}, [%2]! \n\t" // M2[m0-m7]
  29. "vld1.32 {q10, q11}, [%2] \n\t" // M2[m8-m15]
  30. "vadd.f32 q12, q0, q8 \n\t" // DST->M[m0-m3] = M1[m0-m3] + M2[m0-m3]
  31. "vadd.f32 q13, q1, q9 \n\t" // DST->M[m4-m7] = M1[m4-m7] + M2[m4-m7]
  32. "vadd.f32 q14, q2, q10 \n\t" // DST->M[m8-m11] = M1[m8-m11] + M2[m8-m11]
  33. "vadd.f32 q15, q3, q11 \n\t" // DST->M[m12-m15] = M1[m12-m15] + M2[m12-m15]
  34. "vst1.32 {q12, q13}, [%0]! \n\t" // DST->M[m0-m7]
  35. "vst1.32 {q14, q15}, [%0] \n\t" // DST->M[m8-m15]
  36. :
  37. : "r"(dst), "r"(m1), "r"(m2)
  38. : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory"
  39. );
  40. }
  41. inline void MathUtil::subtractMatrix(const float* m1, const float* m2, float* dst)
  42. {
  43. asm volatile(
  44. "vld1.32 {q0, q1}, [%1]! \n\t" // M1[m0-m7]
  45. "vld1.32 {q2, q3}, [%1] \n\t" // M1[m8-m15]
  46. "vld1.32 {q8, q9}, [%2]! \n\t" // M2[m0-m7]
  47. "vld1.32 {q10, q11}, [%2] \n\t" // M2[m8-m15]
  48. "vsub.f32 q12, q0, q8 \n\t" // DST->M[m0-m3] = M1[m0-m3] - M2[m0-m3]
  49. "vsub.f32 q13, q1, q9 \n\t" // DST->M[m4-m7] = M1[m4-m7] - M2[m4-m7]
  50. "vsub.f32 q14, q2, q10 \n\t" // DST->M[m8-m11] = M1[m8-m11] - M2[m8-m11]
  51. "vsub.f32 q15, q3, q11 \n\t" // DST->M[m12-m15] = M1[m12-m15] - M2[m12-m15]
  52. "vst1.32 {q12, q13}, [%0]! \n\t" // DST->M[m0-m7]
  53. "vst1.32 {q14, q15}, [%0] \n\t" // DST->M[m8-m15]
  54. :
  55. : "r"(dst), "r"(m1), "r"(m2)
  56. : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory"
  57. );
  58. }
  59. inline void MathUtil::multiplyMatrix(const float* m, float scalar, float* dst)
  60. {
  61. asm volatile(
  62. "vld1.32 {d0[0]}, [%2] \n\t" // M[m0-m7]
  63. "vld1.32 {q4-q5}, [%1]! \n\t" // M[m8-m15]
  64. "vld1.32 {q6-q7}, [%1] \n\t" // s
  65. "vmul.f32 q8, q4, d0[0] \n\t" // DST->M[m0-m3] = M[m0-m3] * s
  66. "vmul.f32 q9, q5, d0[0] \n\t" // DST->M[m4-m7] = M[m4-m7] * s
  67. "vmul.f32 q10, q6, d0[0] \n\t" // DST->M[m8-m11] = M[m8-m11] * s
  68. "vmul.f32 q11, q7, d0[0] \n\t" // DST->M[m12-m15] = M[m12-m15] * s
  69. "vst1.32 {q8-q9}, [%0]! \n\t" // DST->M[m0-m7]
  70. "vst1.32 {q10-q11}, [%0] \n\t" // DST->M[m8-m15]
  71. :
  72. : "r"(dst), "r"(m), "r"(&scalar)
  73. : "q0", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "memory"
  74. );
  75. }
  76. inline void MathUtil::multiplyMatrix(const float* m1, const float* m2, float* dst)
  77. {
  78. asm volatile(
  79. "vld1.32 {d16 - d19}, [%1]! \n\t" // M1[m0-m7]
  80. "vld1.32 {d20 - d23}, [%1] \n\t" // M1[m8-m15]
  81. "vld1.32 {d0 - d3}, [%2]! \n\t" // M2[m0-m7]
  82. "vld1.32 {d4 - d7}, [%2] \n\t" // M2[m8-m15]
  83. "vmul.f32 q12, q8, d0[0] \n\t" // DST->M[m0-m3] = M1[m0-m3] * M2[m0]
  84. "vmul.f32 q13, q8, d2[0] \n\t" // DST->M[m4-m7] = M1[m4-m7] * M2[m4]
  85. "vmul.f32 q14, q8, d4[0] \n\t" // DST->M[m8-m11] = M1[m8-m11] * M2[m8]
  86. "vmul.f32 q15, q8, d6[0] \n\t" // DST->M[m12-m15] = M1[m12-m15] * M2[m12]
  87. "vmla.f32 q12, q9, d0[1] \n\t" // DST->M[m0-m3] += M1[m0-m3] * M2[m1]
  88. "vmla.f32 q13, q9, d2[1] \n\t" // DST->M[m4-m7] += M1[m4-m7] * M2[m5]
  89. "vmla.f32 q14, q9, d4[1] \n\t" // DST->M[m8-m11] += M1[m8-m11] * M2[m9]
  90. "vmla.f32 q15, q9, d6[1] \n\t" // DST->M[m12-m15] += M1[m12-m15] * M2[m13]
  91. "vmla.f32 q12, q10, d1[0] \n\t" // DST->M[m0-m3] += M1[m0-m3] * M2[m2]
  92. "vmla.f32 q13, q10, d3[0] \n\t" // DST->M[m4-m7] += M1[m4-m7] * M2[m6]
  93. "vmla.f32 q14, q10, d5[0] \n\t" // DST->M[m8-m11] += M1[m8-m11] * M2[m10]
  94. "vmla.f32 q15, q10, d7[0] \n\t" // DST->M[m12-m15] += M1[m12-m15] * M2[m14]
  95. "vmla.f32 q12, q11, d1[1] \n\t" // DST->M[m0-m3] += M1[m0-m3] * M2[m3]
  96. "vmla.f32 q13, q11, d3[1] \n\t" // DST->M[m4-m7] += M1[m4-m7] * M2[m7]
  97. "vmla.f32 q14, q11, d5[1] \n\t" // DST->M[m8-m11] += M1[m8-m11] * M2[m11]
  98. "vmla.f32 q15, q11, d7[1] \n\t" // DST->M[m12-m15] += M1[m12-m15] * M2[m15]
  99. "vst1.32 {d24 - d27}, [%0]! \n\t" // DST->M[m0-m7]
  100. "vst1.32 {d28 - d31}, [%0] \n\t" // DST->M[m8-m15]
  101. : // output
  102. : "r"(dst), "r"(m1), "r"(m2) // input - note *value* of pointer doesn't change.
  103. : "memory", "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15"
  104. );
  105. }
  106. inline void MathUtil::negateMatrix(const float* m, float* dst)
  107. {
  108. asm volatile(
  109. "vld1.32 {q0-q1}, [%1]! \n\t" // load m0-m7
  110. "vld1.32 {q2-q3}, [%1] \n\t" // load m8-m15
  111. "vneg.f32 q4, q0 \n\t" // negate m0-m3
  112. "vneg.f32 q5, q1 \n\t" // negate m4-m7
  113. "vneg.f32 q6, q2 \n\t" // negate m8-m15
  114. "vneg.f32 q7, q3 \n\t" // negate m8-m15
  115. "vst1.32 {q4-q5}, [%0]! \n\t" // store m0-m7
  116. "vst1.32 {q6-q7}, [%0] \n\t" // store m8-m15
  117. :
  118. : "r"(dst), "r"(m)
  119. : "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "memory"
  120. );
  121. }
  122. inline void MathUtil::transposeMatrix(const float* m, float* dst)
  123. {
  124. asm volatile(
  125. "vld4.32 {d0[0], d2[0], d4[0], d6[0]}, [%1]! \n\t" // DST->M[m0, m4, m8, m12] = M[m0-m3]
  126. "vld4.32 {d0[1], d2[1], d4[1], d6[1]}, [%1]! \n\t" // DST->M[m1, m5, m9, m12] = M[m4-m7]
  127. "vld4.32 {d1[0], d3[0], d5[0], d7[0]}, [%1]! \n\t" // DST->M[m2, m6, m10, m12] = M[m8-m11]
  128. "vld4.32 {d1[1], d3[1], d5[1], d7[1]}, [%1] \n\t" // DST->M[m3, m7, m11, m12] = M[m12-m15]
  129. "vst1.32 {q0-q1}, [%0]! \n\t" // DST->M[m0-m7]
  130. "vst1.32 {q2-q3}, [%0] \n\t" // DST->M[m8-m15]
  131. :
  132. : "r"(dst), "r"(m)
  133. : "q0", "q1", "q2", "q3", "memory"
  134. );
  135. }
  136. inline void MathUtil::transformVector4(const float* m, float x, float y, float z, float w, float* dst)
  137. {
  138. asm volatile(
  139. "vld1.32 {d0[0]}, [%1] \n\t" // V[x]
  140. "vld1.32 {d0[1]}, [%2] \n\t" // V[y]
  141. "vld1.32 {d1[0]}, [%3] \n\t" // V[z]
  142. "vld1.32 {d1[1]}, [%4] \n\t" // V[w]
  143. "vld1.32 {d18 - d21}, [%5]! \n\t" // M[m0-m7]
  144. "vld1.32 {d22 - d25}, [%5] \n\t" // M[m8-m15]
  145. "vmul.f32 q13, q9, d0[0] \n\t" // DST->V = M[m0-m3] * V[x]
  146. "vmla.f32 q13, q10, d0[1] \n\t" // DST->V += M[m4-m7] * V[y]
  147. "vmla.f32 q13, q11, d1[0] \n\t" // DST->V += M[m8-m11] * V[z]
  148. "vmla.f32 q13, q12, d1[1] \n\t" // DST->V += M[m12-m15] * V[w]
  149. "vst1.32 {d26}, [%0]! \n\t" // DST->V[x, y]
  150. "vst1.32 {d27[0]}, [%0] \n\t" // DST->V[z]
  151. :
  152. : "r"(dst), "r"(&x), "r"(&y), "r"(&z), "r"(&w), "r"(m)
  153. : "q0", "q9", "q10","q11", "q12", "q13", "memory"
  154. );
  155. }
  156. inline void MathUtil::transformVector4(const float* m, const float* v, float* dst)
  157. {
  158. asm volatile
  159. (
  160. "vld1.32 {d0, d1}, [%1] \n\t" // V[x, y, z, w]
  161. "vld1.32 {d18 - d21}, [%2]! \n\t" // M[m0-m7]
  162. "vld1.32 {d22 - d25}, [%2] \n\t" // M[m8-m15]
  163. "vmul.f32 q13, q9, d0[0] \n\t" // DST->V = M[m0-m3] * V[x]
  164. "vmla.f32 q13, q10, d0[1] \n\t" // DST->V = M[m4-m7] * V[y]
  165. "vmla.f32 q13, q11, d1[0] \n\t" // DST->V = M[m8-m11] * V[z]
  166. "vmla.f32 q13, q12, d1[1] \n\t" // DST->V = M[m12-m15] * V[w]
  167. "vst1.32 {d26, d27}, [%0] \n\t" // DST->V
  168. :
  169. : "r"(dst), "r"(v), "r"(m)
  170. : "q0", "q9", "q10","q11", "q12", "q13", "memory"
  171. );
  172. }
  173. inline void MathUtil::crossVector3(const float* v1, const float* v2, float* dst)
  174. {
  175. asm volatile(
  176. "vld1.32 {d1[1]}, [%1] \n\t" //
  177. "vld1.32 {d0}, [%2] \n\t" //
  178. "vmov.f32 s2, s1 \n\t" // q0 = (v1y, v1z, v1z, v1x)
  179. "vld1.32 {d2[1]}, [%3] \n\t" //
  180. "vld1.32 {d3}, [%4] \n\t" //
  181. "vmov.f32 s4, s7 \n\t" // q1 = (v2z, v2x, v2y, v2z)
  182. "vmul.f32 d4, d0, d2 \n\t" // x = v1y * v2z, y = v1z * v2x
  183. "vmls.f32 d4, d1, d3 \n\t" // x -= v1z * v2y, y-= v1x - v2z
  184. "vmul.f32 d5, d3, d1[1] \n\t" // z = v1x * v2y
  185. "vmls.f32 d5, d0, d2[1] \n\t" // z-= v1y * vx
  186. "vst1.32 {d4}, [%0]! \n\t" // V[x, y]
  187. "vst1.32 {d5[0]}, [%0] \n\t" // V[z]
  188. :
  189. : "r"(dst), "r"(v1), "r"((v1+1)), "r"(v2), "r"((v2+1))
  190. : "q0", "q1", "q2", "memory"
  191. );
  192. }
  193. }