pixel-a.S 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535
  1. /*****************************************************************************
  2. * pixel.S: arm pixel metrics
  3. *****************************************************************************
  4. * Copyright (C) 2009-2018 x264 project
  5. *
  6. * Authors: David Conrad <lessen42@gmail.com>
  7. * Janne Grunau <janne-x264@jannau.net>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
  22. *
  23. * This program is also available under a commercial proprietary license.
  24. * For more information, contact us at licensing@x264.com.
  25. *****************************************************************************/
  26. #include "asm.S"
  27. const mask_array, align=4
  28. .rept 16
  29. .byte 0xff
  30. .endr
  31. mask_ff:
  32. .rept 16
  33. .byte 0
  34. .endr
  35. endconst
  36. const mask_ac4, align=4
  37. .short 0, -1, -1, -1, 0, -1, -1, -1
  38. endconst
  39. const mask_ac8, align=4
  40. .short 0, -1, -1, -1, -1, -1, -1, -1
  41. endconst
  42. .text
  43. .macro SAD4_ARMV6 h
  44. function pixel_sad_4x\h\()_armv6
  45. push {r4-r6,lr}
  46. ldr r4, [r2], r3
  47. ldr r5, [r0], r1
  48. ldr r6, [r2], r3
  49. ldr lr, [r0], r1
  50. usad8 ip, r4, r5
  51. .rept (\h - 2)/2
  52. ldr r4, [r2], r3
  53. ldr r5, [r0], r1
  54. usada8 ip, r6, lr, ip
  55. ldr r6, [r2], r3
  56. ldr lr, [r0], r1
  57. usada8 ip, r4, r5, ip
  58. .endr
  59. usada8 r0, r6, lr, ip
  60. pop {r4-r6,pc}
  61. endfunc
  62. .endm
  63. SAD4_ARMV6 4
  64. SAD4_ARMV6 8
  65. .macro SAD_START_4 align:vararg
  66. vld1.32 {d1[]}, [r2\align], r3
  67. vld1.32 {d0[]}, [r0,:32], r1
  68. vabdl.u8 q8, d0, d1
  69. .endm
  70. .macro SAD_4 align:vararg
  71. vld1.32 {d1[]}, [r2\align], r3
  72. vld1.32 {d0[]}, [r0,:32], r1
  73. vabal.u8 q8, d0, d1
  74. .endm
  75. .macro SAD_START_8 align:vararg
  76. vld1.64 {d1}, [r2\align], r3
  77. vld1.64 {d0}, [r0,:64], r1
  78. vabdl.u8 q8, d0, d1
  79. .endm
  80. .macro SAD_8 align:vararg
  81. vld1.64 {d1}, [r2\align], r3
  82. vld1.64 {d0}, [r0,:64], r1
  83. vabal.u8 q8, d0, d1
  84. .endm
  85. .macro SAD_START_16 align:vararg
  86. vld1.64 {d2-d3}, [r2\align], r3
  87. vld1.64 {d0-d1}, [r0,:128], r1
  88. vabdl.u8 q8, d0, d2
  89. vld1.64 {d6-d7}, [r2\align], r3
  90. vabdl.u8 q9, d1, d3
  91. vld1.64 {d4-d5}, [r0,:128], r1
  92. .endm
  93. .macro SAD_16 align:vararg
  94. vabal.u8 q8, d4, d6
  95. vld1.64 {d2-d3}, [r2\align], r3
  96. vabal.u8 q9, d5, d7
  97. vld1.64 {d0-d1}, [r0,:128], r1
  98. vabal.u8 q8, d0, d2
  99. vld1.64 {d6-d7}, [r2\align], r3
  100. vabal.u8 q9, d1, d3
  101. vld1.64 {d4-d5}, [r0,:128], r1
  102. .endm
  103. .macro SAD_FUNC w, h, name, align:vararg
  104. function pixel_sad\name\()_\w\()x\h\()_neon
  105. SAD_START_\w \align
  106. .if \w == 16
  107. .rept \h / 2 - 1
  108. SAD_\w \align
  109. .endr
  110. .else
  111. .rept \h - 1
  112. SAD_\w \align
  113. .endr
  114. .endif
  115. .if \w > 8
  116. vabal.u8 q8, d4, d6
  117. vabal.u8 q9, d5, d7
  118. vadd.u16 q8, q8, q9
  119. .endif
  120. .if \w > 4
  121. vadd.u16 d16, d16, d17
  122. .endif
  123. vpadd.u16 d0, d16, d16
  124. vpaddl.u16 d0, d0
  125. vmov.u32 r0, d0[0]
  126. bx lr
  127. endfunc
  128. .endm
  129. SAD_FUNC 4, 4
  130. SAD_FUNC 4, 8
  131. SAD_FUNC 8, 4
  132. SAD_FUNC 8, 8
  133. SAD_FUNC 8, 16
  134. SAD_FUNC 16, 8
  135. SAD_FUNC 16, 16
  136. SAD_FUNC 4, 4, _aligned, ,:32
  137. SAD_FUNC 4, 8, _aligned, ,:32
  138. SAD_FUNC 8, 4, _aligned, ,:64
  139. SAD_FUNC 8, 8, _aligned, ,:64
  140. SAD_FUNC 8, 16, _aligned, ,:64
  141. SAD_FUNC 16, 8, _aligned, ,:128
  142. SAD_FUNC 16, 16, _aligned, ,:128
  143. // If dual issue is possible, use additional accumulators to avoid
  144. // stalls from vadal's latency. This only matters for aligned.
  145. .macro SAD_DUAL_START_8
  146. SAD_START_8 ,:64
  147. vld1.64 {d3}, [r2,:64], r3
  148. vld1.64 {d2}, [r0,:64], r1
  149. vabdl.u8 q9, d2, d3
  150. .endm
  151. .macro SAD_DUAL_8 align:vararg
  152. vld1.64 {d1}, [r2,:64], r3
  153. vld1.64 {d0}, [r0,:64], r1
  154. vabal.u8 q8, d0, d1
  155. vld1.64 {d3}, [r2,:64], r3
  156. vld1.64 {d2}, [r0,:64], r1
  157. vabal.u8 q9, d2, d3
  158. .endm
  159. .macro SAD_DUAL_START_16
  160. SAD_START_16 ,:128
  161. vabdl.u8 q10, d4, d6
  162. vld1.64 {d2-d3}, [r2,:128], r3
  163. vabdl.u8 q11, d5, d7
  164. vld1.64 {d0-d1}, [r0,:128], r1
  165. .endm
  166. .macro SAD_DUAL_16
  167. vabal.u8 q8, d0, d2
  168. vld1.64 {d6-d7}, [r2,:128], r3
  169. vabal.u8 q9, d1, d3
  170. vld1.64 {d4-d5}, [r0,:128], r1
  171. vabal.u8 q10, d4, d6
  172. vld1.64 {d2-d3}, [r2,:128], r3
  173. vabal.u8 q11, d5, d7
  174. vld1.64 {d0-d1}, [r0,:128], r1
  175. .endm
  176. .macro SAD_DUAL_END_16
  177. vabal.u8 q8, d0, d2
  178. vld1.64 {d6-d7}, [r2,:128], r3
  179. vabal.u8 q9, d1, d3
  180. vld1.64 {d4-d5}, [r0,:128], r1
  181. vabal.u8 q10, d4, d6
  182. vabal.u8 q11, d5, d7
  183. .endm
  184. .macro SAD_FUNC_DUAL w, h
  185. function pixel_sad_aligned_\w\()x\h\()_neon_dual
  186. SAD_DUAL_START_\w
  187. .rept \h / 2 - \w / 8
  188. SAD_DUAL_\w
  189. .endr
  190. .if \w > 8
  191. SAD_DUAL_END_16
  192. vadd.u16 q8, q8, q9
  193. vadd.u16 q9, q10, q11
  194. .endif
  195. .if \w > 4
  196. vadd.u16 q8, q8, q9
  197. vadd.u16 d16, d16, d17
  198. .endif
  199. vpadd.u16 d0, d16, d16
  200. vpaddl.u16 d0, d0
  201. vmov.u32 r0, d0[0]
  202. bx lr
  203. endfunc
  204. .endm
  205. SAD_FUNC_DUAL 8, 4
  206. SAD_FUNC_DUAL 8, 8
  207. SAD_FUNC_DUAL 8, 16
  208. SAD_FUNC_DUAL 16, 8
  209. SAD_FUNC_DUAL 16, 16
  210. .macro SAD_X_START_4 x
  211. vld1.32 {d0[]}, [r0,:32], lr
  212. vld1.32 {d1[]}, [r1], r6
  213. vabdl.u8 q8, d1, d0
  214. vld1.32 {d2[]}, [r2], r6
  215. vabdl.u8 q9, d2, d0
  216. vld1.32 {d3[]}, [r3], r6
  217. vabdl.u8 q10, d3, d0
  218. .if \x == 4
  219. vld1.32 {d4[]}, [r12], r6
  220. vabdl.u8 q11, d4, d0
  221. .endif
  222. .endm
  223. .macro SAD_X_4 x
  224. vld1.32 {d0[]}, [r0,:32], lr
  225. vld1.32 {d1[]}, [r1], r6
  226. vabal.u8 q8, d1, d0
  227. vld1.32 {d2[]}, [r2], r6
  228. vabal.u8 q9, d2, d0
  229. vld1.32 {d3[]}, [r3], r6
  230. vabal.u8 q10, d3, d0
  231. .if \x == 4
  232. vld1.32 {d4[]}, [r12], r6
  233. vabal.u8 q11, d4, d0
  234. .endif
  235. .endm
  236. .macro SAD_X_START_8 x
  237. vld1.64 {d0}, [r0,:64], lr
  238. vld1.64 {d1}, [r1], r6
  239. vabdl.u8 q8, d1, d0
  240. vld1.64 {d2}, [r2], r6
  241. vabdl.u8 q9, d2, d0
  242. vld1.64 {d3}, [r3], r6
  243. vabdl.u8 q10, d3, d0
  244. .if \x == 4
  245. vld1.64 {d4}, [r12], r6
  246. vabdl.u8 q11, d4, d0
  247. .endif
  248. .endm
  249. .macro SAD_X_8 x
  250. vld1.64 {d0}, [r0,:64], lr
  251. vld1.64 {d1}, [r1], r6
  252. vabal.u8 q8, d1, d0
  253. vld1.64 {d2}, [r2], r6
  254. vabal.u8 q9, d2, d0
  255. vld1.64 {d3}, [r3], r6
  256. vabal.u8 q10, d3, d0
  257. .if \x == 4
  258. vld1.64 {d4}, [r12], r6
  259. vabal.u8 q11, d4, d0
  260. .endif
  261. .endm
  262. .macro SAD_X_START_16 x
  263. vld1.64 {d0-d1}, [r0,:128], lr
  264. vld1.64 {d2-d3}, [r1], r6
  265. vabdl.u8 q8, d2, d0
  266. vabdl.u8 q12, d3, d1
  267. vld1.64 {d4-d5}, [r2], r6
  268. vabdl.u8 q9, d4, d0
  269. vabdl.u8 q13, d5, d1
  270. vld1.64 {d6-d7}, [r3], r6
  271. vabdl.u8 q10, d6, d0
  272. vabdl.u8 q14, d7, d1
  273. .if \x == 4
  274. vld1.64 {d2-d3}, [r12], r6
  275. vabdl.u8 q11, d2, d0
  276. vabdl.u8 q15, d3, d1
  277. .endif
  278. .endm
  279. .macro SAD_X_16 x
  280. vld1.64 {d0-d1}, [r0,:128], lr
  281. vld1.64 {d2-d3}, [r1], r6
  282. vabal.u8 q8, d2, d0
  283. vabal.u8 q12, d3, d1
  284. vld1.64 {d4-d5}, [r2], r6
  285. vabal.u8 q9, d4, d0
  286. vabal.u8 q13, d5, d1
  287. vld1.64 {d6-d7}, [r3], r6
  288. vabal.u8 q10, d6, d0
  289. vabal.u8 q14, d7, d1
  290. .if \x == 4
  291. vld1.64 {d2-d3}, [r12], r6
  292. vabal.u8 q11, d2, d0
  293. vabal.u8 q15, d3, d1
  294. .endif
  295. .endm
  296. .macro SAD_X_FUNC x, w, h
  297. function pixel_sad_x\x\()_\w\()x\h\()_neon
  298. push {r6-r7,lr}
  299. .if \x == 3
  300. ldrd r6, r7, [sp, #12]
  301. .else
  302. ldrd r6, r7, [sp, #16]
  303. ldr r12, [sp, #12]
  304. .endif
  305. mov lr, #FENC_STRIDE
  306. SAD_X_START_\w \x
  307. .rept \h - 1
  308. SAD_X_\w \x
  309. .endr
  310. // add up the sads
  311. .if \w > 8
  312. vadd.u16 q8, q8, q12
  313. vadd.u16 q9, q9, q13
  314. vadd.u16 q10, q10, q14
  315. .if \x == 4
  316. vadd.u16 q11, q11, q15
  317. .endif
  318. .endif
  319. .if \w > 4
  320. vadd.u16 d16, d16, d17
  321. vadd.u16 d18, d18, d19
  322. vadd.u16 d20, d20, d21
  323. .if \x == 4
  324. vadd.u16 d22, d22, d23
  325. .endif
  326. .endif
  327. vpadd.u16 d0, d16, d18
  328. vpadd.u16 d1, d20, d22
  329. vpaddl.u16 q0, q0
  330. .if \x == 3
  331. vst1.32 {d0}, [r7]!
  332. vst1.32 {d1[0]}, [r7,:32]
  333. .else
  334. vst1.32 {d0-d1}, [r7]
  335. .endif
  336. pop {r6-r7,pc}
  337. endfunc
  338. .endm
  339. SAD_X_FUNC 3, 4, 4
  340. SAD_X_FUNC 3, 4, 8
  341. SAD_X_FUNC 3, 8, 4
  342. SAD_X_FUNC 3, 8, 8
  343. SAD_X_FUNC 3, 8, 16
  344. SAD_X_FUNC 3, 16, 8
  345. SAD_X_FUNC 3, 16, 16
  346. SAD_X_FUNC 4, 4, 4
  347. SAD_X_FUNC 4, 4, 8
  348. SAD_X_FUNC 4, 8, 4
  349. SAD_X_FUNC 4, 8, 8
  350. SAD_X_FUNC 4, 8, 16
  351. SAD_X_FUNC 4, 16, 8
  352. SAD_X_FUNC 4, 16, 16
  353. function pixel_vsad_neon
  354. subs r2, r2, #2
  355. vld1.8 {q0}, [r0], r1
  356. vld1.8 {q1}, [r0], r1
  357. vabdl.u8 q2, d0, d2
  358. vabdl.u8 q3, d1, d3
  359. ble 2f
  360. 1:
  361. subs r2, r2, #2
  362. vld1.8 {q0}, [r0], r1
  363. vabal.u8 q2, d2, d0
  364. vabal.u8 q3, d3, d1
  365. vld1.8 {q1}, [r0], r1
  366. blt 2f
  367. vabal.u8 q2, d0, d2
  368. vabal.u8 q3, d1, d3
  369. bgt 1b
  370. 2:
  371. vadd.u16 q0, q2, q3
  372. HORIZ_ADD d0, d0, d1
  373. vmov.32 r0, d0[0]
  374. bx lr
  375. endfunc
  376. function pixel_asd8_neon
  377. ldr r12, [sp, #0]
  378. sub r12, r12, #2
  379. vld1.8 {d0}, [r0], r1
  380. vld1.8 {d1}, [r2], r3
  381. vld1.8 {d2}, [r0], r1
  382. vld1.8 {d3}, [r2], r3
  383. vsubl.u8 q8, d0, d1
  384. 1:
  385. subs r12, r12, #2
  386. vld1.8 {d4}, [r0], r1
  387. vld1.8 {d5}, [r2], r3
  388. vsubl.u8 q9, d2, d3
  389. vsubl.u8 q10, d4, d5
  390. vadd.s16 q8, q9
  391. vld1.8 {d2}, [r0], r1
  392. vld1.8 {d3}, [r2], r3
  393. vadd.s16 q8, q10
  394. bgt 1b
  395. vsubl.u8 q9, d2, d3
  396. vadd.s16 q8, q9
  397. vpaddl.s16 q8, q8
  398. vpadd.s32 d16, d16, d17
  399. vpadd.s32 d16, d16, d17
  400. vabs.s32 d16, d16
  401. vmov.32 r0, d16[0]
  402. bx lr
  403. endfunc
  404. .macro SSD_START_4
  405. vld1.32 {d16[]}, [r0,:32], r1
  406. vld1.32 {d17[]}, [r2,:32], r3
  407. vsubl.u8 q2, d16, d17
  408. vld1.32 {d16[]}, [r0,:32], r1
  409. vmull.s16 q0, d4, d4
  410. vld1.32 {d17[]}, [r2,:32], r3
  411. .endm
  412. .macro SSD_4
  413. vsubl.u8 q2, d16, d17
  414. vld1.32 {d16[]}, [r0,:32], r1
  415. vmlal.s16 q0, d4, d4
  416. vld1.32 {d17[]}, [r2,:32], r3
  417. .endm
  418. .macro SSD_END_4
  419. vsubl.u8 q2, d16, d17
  420. vmlal.s16 q0, d4, d4
  421. .endm
  422. .macro SSD_START_8
  423. vld1.64 {d16}, [r0,:64], r1
  424. vld1.64 {d17}, [r2,:64], r3
  425. vsubl.u8 q2, d16, d17
  426. vld1.64 {d16}, [r0,:64], r1
  427. vmull.s16 q0, d4, d4
  428. vmlal.s16 q0, d5, d5
  429. vld1.64 {d17}, [r2,:64], r3
  430. .endm
  431. .macro SSD_8
  432. vsubl.u8 q2, d16, d17
  433. vld1.64 {d16}, [r0,:64], r1
  434. vmlal.s16 q0, d4, d4
  435. vmlal.s16 q0, d5, d5
  436. vld1.64 {d17}, [r2,:64], r3
  437. .endm
  438. .macro SSD_END_8
  439. vsubl.u8 q2, d16, d17
  440. vmlal.s16 q0, d4, d4
  441. vmlal.s16 q0, d5, d5
  442. .endm
  443. .macro SSD_START_16
  444. vld1.64 {d16-d17}, [r0,:128], r1
  445. vld1.64 {d18-d19}, [r2,:128], r3
  446. vsubl.u8 q2, d16, d18
  447. vsubl.u8 q3, d17, d19
  448. vld1.64 {d16-d17}, [r0,:128], r1
  449. vmull.s16 q0, d4, d4
  450. vmlal.s16 q0, d5, d5
  451. vld1.64 {d18-d19}, [r2,:128], r3
  452. vmlal.s16 q0, d6, d6
  453. vmlal.s16 q0, d7, d7
  454. .endm
  455. .macro SSD_16
  456. vsubl.u8 q2, d16, d18
  457. vsubl.u8 q3, d17, d19
  458. vld1.64 {d16-d17}, [r0,:128], r1
  459. vmlal.s16 q0, d4, d4
  460. vmlal.s16 q0, d5, d5
  461. vld1.64 {d18-d19}, [r2,:128], r3
  462. vmlal.s16 q0, d6, d6
  463. vmlal.s16 q0, d7, d7
  464. .endm
  465. .macro SSD_END_16
  466. vsubl.u8 q2, d16, d18
  467. vsubl.u8 q3, d17, d19
  468. vmlal.s16 q0, d4, d4
  469. vmlal.s16 q0, d5, d5
  470. vmlal.s16 q0, d6, d6
  471. vmlal.s16 q0, d7, d7
  472. .endm
  473. .macro SSD_FUNC w h
  474. function pixel_ssd_\w\()x\h\()_neon
  475. SSD_START_\w
  476. .rept \h-2
  477. SSD_\w
  478. .endr
  479. SSD_END_\w
  480. vadd.s32 d0, d0, d1
  481. vpadd.s32 d0, d0, d0
  482. vmov.32 r0, d0[0]
  483. bx lr
  484. endfunc
  485. .endm
  486. SSD_FUNC 4, 4
  487. SSD_FUNC 4, 8
  488. SSD_FUNC 8, 4
  489. SSD_FUNC 8, 8
  490. SSD_FUNC 8, 16
  491. SSD_FUNC 16, 8
  492. SSD_FUNC 16, 16
  493. function pixel_ssd_nv12_core_neon
  494. push {r4-r5}
  495. ldrd r4, r5, [sp, #8]
  496. add r12, r4, #8
  497. bic r12, r12, #15
  498. vmov.u64 q8, #0
  499. vmov.u64 q9, #0
  500. sub r1, r1, r12, lsl #1
  501. sub r3, r3, r12, lsl #1
  502. 1:
  503. subs r12, r4, #16
  504. vld2.8 {d0,d1}, [r0]!
  505. vld2.8 {d2,d3}, [r2]!
  506. vld2.8 {d4,d5}, [r0]!
  507. vld2.8 {d6,d7}, [r2]!
  508. vsubl.u8 q10, d0, d2
  509. vsubl.u8 q11, d1, d3
  510. vmull.s16 q14, d20, d20
  511. vmull.s16 q15, d22, d22
  512. vsubl.u8 q12, d4, d6
  513. vsubl.u8 q13, d5, d7
  514. vmlal.s16 q14, d21, d21
  515. vmlal.s16 q15, d23, d23
  516. blt 4f
  517. beq 3f
  518. 2:
  519. vmlal.s16 q14, d24, d24
  520. vmlal.s16 q15, d26, d26
  521. vld2.8 {d0,d1}, [r0]!
  522. vld2.8 {d2,d3}, [r2]!
  523. vmlal.s16 q14, d25, d25
  524. vmlal.s16 q15, d27, d27
  525. subs r12, r12, #16
  526. vsubl.u8 q10, d0, d2
  527. vsubl.u8 q11, d1, d3
  528. vmlal.s16 q14, d20, d20
  529. vmlal.s16 q15, d22, d22
  530. vld2.8 {d4,d5}, [r0]!
  531. vld2.8 {d6,d7}, [r2]!
  532. vmlal.s16 q14, d21, d21
  533. vmlal.s16 q15, d23, d23
  534. blt 4f
  535. vsubl.u8 q12, d4, d6
  536. vsubl.u8 q13, d5, d7
  537. bgt 2b
  538. 3:
  539. vmlal.s16 q14, d24, d24
  540. vmlal.s16 q15, d26, d26
  541. vmlal.s16 q14, d25, d25
  542. vmlal.s16 q15, d27, d27
  543. 4:
  544. subs r5, r5, #1
  545. vaddw.s32 q8, q8, d28
  546. vaddw.s32 q9, q9, d30
  547. add r0, r0, r1
  548. add r2, r2, r3
  549. vaddw.s32 q8, q8, d29
  550. vaddw.s32 q9, q9, d31
  551. bgt 1b
  552. vadd.u64 d16, d16, d17
  553. vadd.u64 d18, d18, d19
  554. ldrd r4, r5, [sp, #16]
  555. vst1.64 {d16}, [r4]
  556. vst1.64 {d18}, [r5]
  557. pop {r4-r5}
  558. bx lr
  559. endfunc
  560. .macro VAR_SQR_SUM qsqr_sum qsqr_last qsqr dsrc vpadal=vpadal.u16
  561. vmull.u8 \qsqr, \dsrc, \dsrc
  562. vaddw.u8 q0, q0, \dsrc
  563. \vpadal \qsqr_sum, \qsqr_last
  564. .endm
  565. function pixel_var_8x8_neon
  566. vld1.64 {d16}, [r0,:64], r1
  567. vmull.u8 q1, d16, d16
  568. vmovl.u8 q0, d16
  569. vld1.64 {d18}, [r0,:64], r1
  570. vmull.u8 q2, d18, d18
  571. vaddw.u8 q0, q0, d18
  572. vld1.64 {d20}, [r0,:64], r1
  573. VAR_SQR_SUM q1, q1, q3, d20, vpaddl.u16
  574. vld1.64 {d22}, [r0,:64], r1
  575. VAR_SQR_SUM q2, q2, q8, d22, vpaddl.u16
  576. vld1.64 {d24}, [r0,:64], r1
  577. VAR_SQR_SUM q1, q3, q9, d24
  578. vld1.64 {d26}, [r0,:64], r1
  579. VAR_SQR_SUM q2, q8, q10, d26
  580. vld1.64 {d24}, [r0,:64], r1
  581. VAR_SQR_SUM q1, q9, q14, d24
  582. vld1.64 {d26}, [r0,:64], r1
  583. VAR_SQR_SUM q2, q10, q15, d26
  584. b var_end
  585. endfunc
  586. function pixel_var_8x16_neon
  587. vld1.64 {d16}, [r0,:64], r1
  588. vld1.64 {d18}, [r0,:64], r1
  589. vmull.u8 q1, d16, d16
  590. vmovl.u8 q0, d16
  591. vld1.64 {d20}, [r0,:64], r1
  592. vmull.u8 q2, d18, d18
  593. vaddw.u8 q0, q0, d18
  594. mov ip, #12
  595. vld1.64 {d22}, [r0,:64], r1
  596. VAR_SQR_SUM q1, q1, q14, d20, vpaddl.u16
  597. vld1.64 {d16}, [r0,:64], r1
  598. VAR_SQR_SUM q2, q2, q15, d22, vpaddl.u16
  599. 1: subs ip, ip, #4
  600. vld1.64 {d18}, [r0,:64], r1
  601. VAR_SQR_SUM q1, q14, q12, d16
  602. vld1.64 {d20}, [r0,:64], r1
  603. VAR_SQR_SUM q2, q15, q13, d18
  604. vld1.64 {d22}, [r0,:64], r1
  605. VAR_SQR_SUM q1, q12, q14, d20
  606. beq 2f
  607. vld1.64 {d16}, [r0,:64], r1
  608. VAR_SQR_SUM q2, q13, q15, d22
  609. b 1b
  610. 2:
  611. VAR_SQR_SUM q2, q13, q15, d22
  612. b var_end
  613. endfunc
  614. function pixel_var_16x16_neon
  615. vld1.64 {d16-d17}, [r0,:128], r1
  616. vmull.u8 q12, d16, d16
  617. vmovl.u8 q0, d16
  618. vmull.u8 q13, d17, d17
  619. vaddw.u8 q0, q0, d17
  620. vld1.64 {d18-d19}, [r0,:128], r1
  621. VAR_SQR_SUM q1, q12, q14, d18, vpaddl.u16
  622. VAR_SQR_SUM q2, q13, q15, d19, vpaddl.u16
  623. mov ip, #7
  624. var16_loop:
  625. subs ip, ip, #1
  626. vld1.64 {d16-d17}, [r0,:128], r1
  627. VAR_SQR_SUM q1, q14, q12, d16
  628. VAR_SQR_SUM q2, q15, q13, d17
  629. vld1.64 {d18-d19}, [r0,:128], r1
  630. VAR_SQR_SUM q1, q12, q14, d18
  631. VAR_SQR_SUM q2, q13, q15, d19
  632. bgt var16_loop
  633. endfunc
  634. function var_end, export=0
  635. vpaddl.u16 q8, q14
  636. vpaddl.u16 q9, q15
  637. vadd.u32 q1, q1, q8
  638. vadd.u16 d0, d0, d1
  639. vadd.u32 q1, q1, q9
  640. vadd.u32 q1, q1, q2
  641. vpaddl.u16 d0, d0
  642. vadd.u32 d2, d2, d3
  643. vpadd.u32 d0, d0, d2
  644. vmov r0, r1, d0
  645. bx lr
  646. endfunc
  647. .macro DIFF_SUM diff1 diff2 da1 db1 da2 db2 lastdiff1 lastdiff2 acc1 acc2
  648. vld1.64 {\da1}, [r0,:64]!
  649. vld1.64 {\db1}, [r1,:64], r3
  650. .ifnb \lastdiff1
  651. vadd.s16 \acc1, \acc1, \lastdiff1
  652. vadd.s16 \acc2, \acc2, \lastdiff2
  653. .endif
  654. vld1.64 {\da2}, [r0,:64]!
  655. vld1.64 {\db2}, [r1,:64], r3
  656. vsubl.u8 \diff1, \da1, \db1
  657. vsubl.u8 \diff2, \da2, \db2
  658. .endm
  659. .macro SQR_ACC_DOUBLE acc1 acc2 d0 d1 d2 d3 vmlal=vmlal.s16
  660. \vmlal \acc1, \d0, \d0
  661. vmlal.s16 \acc1, \d1, \d1
  662. \vmlal \acc2, \d2, \d2
  663. vmlal.s16 \acc2, \d3, \d3
  664. .endm
  665. .macro SQR_ACC acc d0 d1 vmlal=vmlal.s16
  666. \vmlal \acc, \d0, \d0
  667. vmlal.s16 \acc, \d1, \d1
  668. .endm
  669. function pixel_var2_8x8_neon
  670. mov r3, #16
  671. DIFF_SUM q0, q10, d0, d1, d20, d21
  672. DIFF_SUM q8, q11, d16, d17, d22, d23
  673. SQR_ACC_DOUBLE q1, q13, d0, d1, d20, d21, vmull.s16
  674. DIFF_SUM q9, q12, d18, d19, d24, d25, q8, q11, q0, q10
  675. SQR_ACC_DOUBLE q2, q14, d16, d17, d22, d23, vmull.s16
  676. .rept 2
  677. DIFF_SUM q8, q11, d16, d17, d22, d23, q9, q12, q0, q10
  678. SQR_ACC_DOUBLE q1, q13, d18, d19, d24, d25
  679. DIFF_SUM q9, q12, d18, d19, d24, d25, q8, q11, q0, q10
  680. SQR_ACC_DOUBLE q2, q14, d16, d17, d22, d23
  681. .endr
  682. DIFF_SUM q8, q11, d16, d17, d22, d23, q9, q12, q0, q10
  683. SQR_ACC_DOUBLE q1, q13, d18, d19, d24, d25
  684. vadd.s16 q0, q0, q8
  685. vadd.s16 q10, q10, q11
  686. SQR_ACC_DOUBLE q2, q14, d16, d17, d22, d23
  687. vadd.s16 d0, d0, d1
  688. vadd.s16 d20, d20, d21
  689. vadd.s32 q1, q1, q2
  690. vadd.s32 q13, q13, q14
  691. vpaddl.s16 d0, d0
  692. vpaddl.s16 d20, d20
  693. vadd.s32 d1, d2, d3
  694. vadd.s32 d26, d26, d27
  695. vpadd.s32 d0, d0, d20 @ sum
  696. vpadd.s32 d1, d1, d26 @ sqr
  697. vmul.s32 d0, d0, d0 @ sum*sum
  698. vshr.s32 d0, d0, #6
  699. vsub.s32 d0, d1, d0
  700. vpadd.s32 d0, d0, d0
  701. vmov r0, r1, d0
  702. vst1.32 {d1}, [r2,:64]
  703. bx lr
  704. endfunc
  705. function pixel_var2_8x16_neon
  706. mov r3, #16
  707. vld1.64 {d16}, [r0,:64]!
  708. vld1.64 {d17}, [r1,:64], r3
  709. vld1.64 {d18}, [r0,:64]!
  710. vld1.64 {d19}, [r1,:64], r3
  711. vsubl.u8 q0, d16, d17
  712. vsubl.u8 q3, d18, d19
  713. SQR_ACC q1, d0, d1, vmull.s16
  714. vld1.64 {d16}, [r0,:64]!
  715. mov ip, #15
  716. vld1.64 {d17}, [r1,:64], r3
  717. SQR_ACC q2, d6, d7, vmull.s16
  718. 1: subs ip, ip, #1
  719. vld1.64 {d18}, [r0,:64]!
  720. vsubl.u8 q10, d16, d17
  721. vld1.64 {d19}, [r1,:64], r3
  722. vadd.s16 q0, q0, q10
  723. SQR_ACC q1, d20, d21
  724. vsubl.u8 q11, d18, d19
  725. beq 2f
  726. vld1.64 {d16}, [r0,:64]!
  727. vadd.s16 q3, q3, q11
  728. vld1.64 {d17}, [r1,:64], r3
  729. SQR_ACC q2, d22, d23
  730. b 1b
  731. 2:
  732. vadd.s16 q3, q3, q11
  733. SQR_ACC q2, d22, d23
  734. vadd.s16 d0, d0, d1
  735. vadd.s16 d6, d6, d7
  736. vpaddl.s16 d0, d0
  737. vpaddl.s16 d6, d6
  738. vadd.s32 d2, d2, d3
  739. vadd.s32 d4, d4, d5
  740. vpadd.s32 d0, d0, d6 @ sum
  741. vpadd.s32 d2, d2, d4 @ sqr
  742. vmul.s32 d0, d0, d0 @ sum*sum
  743. vshr.s32 d0, d0, #7
  744. vsub.s32 d0, d2, d0
  745. vpadd.s32 d0, d0, d0
  746. vmov r0, r1, d0
  747. vst1.32 {d2}, [r2,:64]
  748. bx lr
  749. endfunc
  750. .macro LOAD_DIFF_8x4 q0 q1 q2 q3
  751. vld1.32 {d1}, [r2], r3
  752. vld1.32 {d0}, [r0,:64], r1
  753. vsubl.u8 \q0, d0, d1
  754. vld1.32 {d3}, [r2], r3
  755. vld1.32 {d2}, [r0,:64], r1
  756. vsubl.u8 \q1, d2, d3
  757. vld1.32 {d5}, [r2], r3
  758. vld1.32 {d4}, [r0,:64], r1
  759. vsubl.u8 \q2, d4, d5
  760. vld1.32 {d7}, [r2], r3
  761. vld1.32 {d6}, [r0,:64], r1
  762. vsubl.u8 \q3, d6, d7
  763. .endm
  764. function pixel_satd_4x4_neon
  765. vld1.32 {d1[]}, [r2], r3
  766. vld1.32 {d0[]}, [r0,:32], r1
  767. vld1.32 {d3[]}, [r2], r3
  768. vld1.32 {d2[]}, [r0,:32], r1
  769. vld1.32 {d1[1]}, [r2], r3
  770. vld1.32 {d0[1]}, [r0,:32], r1
  771. vld1.32 {d3[1]}, [r2], r3
  772. vld1.32 {d2[1]}, [r0,:32], r1
  773. vsubl.u8 q0, d0, d1
  774. vsubl.u8 q1, d2, d3
  775. SUMSUB_AB q2, q3, q0, q1
  776. SUMSUB_ABCD d0, d2, d1, d3, d4, d5, d6, d7
  777. HADAMARD 1, sumsub, q2, q3, q0, q1
  778. HADAMARD 2, amax, q0,, q2, q3
  779. HORIZ_ADD d0, d0, d1
  780. vmov.32 r0, d0[0]
  781. bx lr
  782. endfunc
  783. function pixel_satd_4x8_neon
  784. vld1.32 {d1[]}, [r2], r3
  785. vld1.32 {d0[]}, [r0,:32], r1
  786. vld1.32 {d3[]}, [r2], r3
  787. vld1.32 {d2[]}, [r0,:32], r1
  788. vld1.32 {d5[]}, [r2], r3
  789. vld1.32 {d4[]}, [r0,:32], r1
  790. vld1.32 {d7[]}, [r2], r3
  791. vld1.32 {d6[]}, [r0,:32], r1
  792. vld1.32 {d1[1]}, [r2], r3
  793. vld1.32 {d0[1]}, [r0,:32], r1
  794. vsubl.u8 q0, d0, d1
  795. vld1.32 {d3[1]}, [r2], r3
  796. vld1.32 {d2[1]}, [r0,:32], r1
  797. vsubl.u8 q1, d2, d3
  798. vld1.32 {d5[1]}, [r2], r3
  799. vld1.32 {d4[1]}, [r0,:32], r1
  800. vsubl.u8 q2, d4, d5
  801. vld1.32 {d7[1]}, [r2], r3
  802. SUMSUB_AB q8, q9, q0, q1
  803. vld1.32 {d6[1]}, [r0,:32], r1
  804. vsubl.u8 q3, d6, d7
  805. SUMSUB_AB q10, q11, q2, q3
  806. b satd_4x8_8x4_end_neon
  807. endfunc
  808. function pixel_satd_8x4_neon
  809. vld1.64 {d1}, [r2], r3
  810. vld1.64 {d0}, [r0,:64], r1
  811. vsubl.u8 q0, d0, d1
  812. vld1.64 {d3}, [r2], r3
  813. vld1.64 {d2}, [r0,:64], r1
  814. vsubl.u8 q1, d2, d3
  815. vld1.64 {d5}, [r2], r3
  816. vld1.64 {d4}, [r0,:64], r1
  817. vsubl.u8 q2, d4, d5
  818. vld1.64 {d7}, [r2], r3
  819. SUMSUB_AB q8, q9, q0, q1
  820. vld1.64 {d6}, [r0,:64], r1
  821. vsubl.u8 q3, d6, d7
  822. SUMSUB_AB q10, q11, q2, q3
  823. endfunc
  824. function satd_4x8_8x4_end_neon, export=0
  825. vadd.s16 q0, q8, q10
  826. vadd.s16 q1, q9, q11
  827. vsub.s16 q2, q8, q10
  828. vsub.s16 q3, q9, q11
  829. vtrn.16 q0, q1
  830. vadd.s16 q8, q0, q1
  831. vtrn.16 q2, q3
  832. vsub.s16 q9, q0, q1
  833. vadd.s16 q10, q2, q3
  834. vsub.s16 q11, q2, q3
  835. vtrn.32 q8, q10
  836. vabs.s16 q8, q8
  837. vtrn.32 q9, q11
  838. vabs.s16 q10, q10
  839. vabs.s16 q9, q9
  840. vabs.s16 q11, q11
  841. vmax.u16 q0, q8, q10
  842. vmax.u16 q1, q9, q11
  843. vadd.u16 q0, q0, q1
  844. HORIZ_ADD d0, d0, d1
  845. vmov.32 r0, d0[0]
  846. bx lr
  847. endfunc
  848. function pixel_satd_8x8_neon
  849. mov ip, lr
  850. bl satd_8x8_neon
  851. vadd.u16 q0, q12, q13
  852. vadd.u16 q1, q14, q15
  853. vadd.u16 q0, q0, q1
  854. HORIZ_ADD d0, d0, d1
  855. mov lr, ip
  856. vmov.32 r0, d0[0]
  857. bx lr
  858. endfunc
  859. function pixel_satd_8x16_neon
  860. vpush {d8-d11}
  861. mov ip, lr
  862. bl satd_8x8_neon
  863. vadd.u16 q4, q12, q13
  864. vadd.u16 q5, q14, q15
  865. bl satd_8x8_neon
  866. vadd.u16 q4, q4, q12
  867. vadd.u16 q5, q5, q13
  868. vadd.u16 q4, q4, q14
  869. vadd.u16 q5, q5, q15
  870. vadd.u16 q0, q4, q5
  871. HORIZ_ADD d0, d0, d1
  872. vpop {d8-d11}
  873. mov lr, ip
  874. vmov.32 r0, d0[0]
  875. bx lr
  876. endfunc
  877. function satd_8x8_neon, export=0
  878. LOAD_DIFF_8x4 q8, q9, q10, q11
  879. vld1.64 {d7}, [r2], r3
  880. SUMSUB_AB q0, q1, q8, q9
  881. vld1.64 {d6}, [r0,:64], r1
  882. vsubl.u8 q12, d6, d7
  883. vld1.64 {d17}, [r2], r3
  884. SUMSUB_AB q2, q3, q10, q11
  885. vld1.64 {d16}, [r0,:64], r1
  886. vsubl.u8 q13, d16, d17
  887. vld1.64 {d19}, [r2], r3
  888. SUMSUB_AB q8, q10, q0, q2
  889. vld1.64 {d18}, [r0,:64], r1
  890. vsubl.u8 q14, d18, d19
  891. vld1.64 {d1}, [r2], r3
  892. SUMSUB_AB q9, q11, q1, q3
  893. vld1.64 {d0}, [r0,:64], r1
  894. vsubl.u8 q15, d0, d1
  895. endfunc
  896. // one vertical hadamard pass and two horizontal
  897. function satd_8x4v_8x8h_neon, export=0
  898. SUMSUB_ABCD q0, q1, q2, q3, q12, q13, q14, q15
  899. vtrn.16 q8, q9
  900. SUMSUB_AB q12, q14, q0, q2
  901. vtrn.16 q10, q11
  902. SUMSUB_AB q13, q15, q1, q3
  903. SUMSUB_AB q0, q1, q8, q9
  904. vtrn.16 q12, q13
  905. SUMSUB_AB q2, q3, q10, q11
  906. vtrn.16 q14, q15
  907. SUMSUB_AB q8, q9, q12, q13
  908. vtrn.32 q0, q2
  909. SUMSUB_AB q10, q11, q14, q15
  910. vtrn.32 q1, q3
  911. ABS2 q0, q2
  912. vtrn.32 q8, q10
  913. ABS2 q1, q3
  914. vtrn.32 q9, q11
  915. ABS2 q8, q10
  916. ABS2 q9, q11
  917. vmax.s16 q12, q0, q2
  918. vmax.s16 q13, q1, q3
  919. vmax.s16 q14, q8, q10
  920. vmax.s16 q15, q9, q11
  921. bx lr
  922. endfunc
  923. function pixel_satd_16x8_neon
  924. vpush {d8-d11}
  925. mov ip, lr
  926. bl satd_16x4_neon
  927. vadd.u16 q4, q12, q13
  928. vadd.u16 q5, q14, q15
  929. bl satd_16x4_neon
  930. vadd.u16 q4, q4, q12
  931. vadd.u16 q5, q5, q13
  932. vadd.u16 q4, q4, q14
  933. vadd.u16 q5, q5, q15
  934. vadd.u16 q0, q4, q5
  935. HORIZ_ADD d0, d0, d1
  936. vpop {d8-d11}
  937. mov lr, ip
  938. vmov.32 r0, d0[0]
  939. bx lr
  940. endfunc
  941. function pixel_satd_16x16_neon
  942. vpush {d8-d11}
  943. mov ip, lr
  944. bl satd_16x4_neon
  945. vadd.u16 q4, q12, q13
  946. vadd.u16 q5, q14, q15
  947. bl satd_16x4_neon
  948. vadd.u16 q4, q4, q12
  949. vadd.u16 q5, q5, q13
  950. vadd.u16 q4, q4, q14
  951. vadd.u16 q5, q5, q15
  952. bl satd_16x4_neon
  953. vadd.u16 q4, q4, q12
  954. vadd.u16 q5, q5, q13
  955. vadd.u16 q4, q4, q14
  956. vadd.u16 q5, q5, q15
  957. bl satd_16x4_neon
  958. vadd.u16 q4, q4, q12
  959. vadd.u16 q5, q5, q13
  960. vadd.u16 q4, q4, q14
  961. vadd.u16 q5, q5, q15
  962. vadd.u16 q0, q4, q5
  963. HORIZ_ADD d0, d0, d1
  964. vpop {d8-d11}
  965. mov lr, ip
  966. vmov.32 r0, d0[0]
  967. bx lr
  968. endfunc
  969. function satd_16x4_neon, export=0
  970. vld1.64 {d2-d3}, [r2], r3
  971. vld1.64 {d0-d1}, [r0,:128], r1
  972. vsubl.u8 q8, d0, d2
  973. vld1.64 {d6-d7}, [r2], r3
  974. vsubl.u8 q12, d1, d3
  975. vld1.64 {d4-d5}, [r0,:128], r1
  976. vsubl.u8 q9, d4, d6
  977. vld1.64 {d2-d3}, [r2], r3
  978. vsubl.u8 q13, d5, d7
  979. vld1.64 {d0-d1}, [r0,:128], r1
  980. vsubl.u8 q10, d0, d2
  981. vld1.64 {d6-d7}, [r2], r3
  982. vsubl.u8 q14, d1, d3
  983. vadd.s16 q0, q8, q9
  984. vld1.64 {d4-d5}, [r0,:128], r1
  985. vsub.s16 q1, q8, q9
  986. vsubl.u8 q11, d4, d6
  987. vsubl.u8 q15, d5, d7
  988. SUMSUB_AB q2, q3, q10, q11
  989. SUMSUB_ABCD q8, q10, q9, q11, q0, q2, q1, q3
  990. b satd_8x4v_8x8h_neon
  991. endfunc
  992. function pixel_sa8d_8x8_neon
  993. mov ip, lr
  994. bl sa8d_8x8_neon
  995. vadd.u16 q0, q8, q9
  996. HORIZ_ADD d0, d0, d1
  997. mov lr, ip
  998. vmov.32 r0, d0[0]
  999. add r0, r0, #1
  1000. lsr r0, r0, #1
  1001. bx lr
  1002. endfunc
  1003. function pixel_sa8d_16x16_neon
  1004. vpush {d8-d11}
  1005. mov ip, lr
  1006. bl sa8d_8x8_neon
  1007. vpaddl.u16 q4, q8
  1008. vpaddl.u16 q5, q9
  1009. bl sa8d_8x8_neon
  1010. vpadal.u16 q4, q8
  1011. vpadal.u16 q5, q9
  1012. sub r0, r0, r1, lsl #4
  1013. sub r2, r2, r3, lsl #4
  1014. add r0, r0, #8
  1015. add r2, r2, #8
  1016. bl sa8d_8x8_neon
  1017. vpadal.u16 q4, q8
  1018. vpadal.u16 q5, q9
  1019. bl sa8d_8x8_neon
  1020. vpaddl.u16 q8, q8
  1021. vpaddl.u16 q9, q9
  1022. vadd.u32 q0, q4, q8
  1023. vadd.u32 q1, q5, q9
  1024. vadd.u32 q0, q0, q1
  1025. vadd.u32 d0, d0, d1
  1026. vpadd.u32 d0, d0, d0
  1027. vpop {d8-d11}
  1028. mov lr, ip
  1029. vmov.32 r0, d0[0]
  1030. add r0, r0, #1
  1031. lsr r0, r0, #1
  1032. bx lr
  1033. endfunc
  1034. .macro HADAMARD4_V r1, r2, r3, r4, t1, t2, t3, t4
  1035. SUMSUB_ABCD \t1, \t2, \t3, \t4, \r1, \r2, \r3, \r4
  1036. SUMSUB_ABCD \r1, \r3, \r2, \r4, \t1, \t3, \t2, \t4
  1037. .endm
  1038. .macro integrated_satd dst, s0, s1, s2, s3
  1039. vmov q0, \s0
  1040. vmov q1, \s1
  1041. vmov q2, \s2
  1042. vmov q3, \s3
  1043. vtrn.16 q0, q1
  1044. vtrn.16 q2, q3
  1045. SUMSUB_AB q6, q7, q0, q1
  1046. SUMSUB_AB q0, q1, q2, q3
  1047. vtrn.32 q6, q0
  1048. vtrn.32 q7, q1
  1049. vabs.s16 q6, q6
  1050. vabs.s16 q0, q0
  1051. vabs.s16 q7, q7
  1052. vabs.s16 q1, q1
  1053. vmax.u16 q6, q6, q0
  1054. vmax.u16 q7, q7, q1
  1055. vadd.i16 q6, q6, q7
  1056. vpadal.u16 \dst, q6
  1057. .endm
  1058. .macro sa8d_satd_8x8 satd=
  1059. function sa8d_\satd\()8x8_neon, export=0
  1060. LOAD_DIFF_8x4 q8, q9, q10, q11
  1061. vld1.64 {d7}, [r2], r3
  1062. SUMSUB_AB q0, q1, q8, q9
  1063. vld1.64 {d6}, [r0,:64], r1
  1064. vsubl.u8 q12, d6, d7
  1065. vld1.64 {d17}, [r2], r3
  1066. SUMSUB_AB q2, q3, q10, q11
  1067. vld1.64 {d16}, [r0,:64], r1
  1068. vsubl.u8 q13, d16, d17
  1069. vld1.64 {d19}, [r2], r3
  1070. SUMSUB_AB q8, q10, q0, q2
  1071. vld1.64 {d18}, [r0,:64], r1
  1072. vsubl.u8 q14, d18, d19
  1073. vld1.64 {d1}, [r2], r3
  1074. SUMSUB_AB q9, q11, q1, q3
  1075. vld1.64 {d0}, [r0,:64], r1
  1076. vsubl.u8 q15, d0, d1
  1077. HADAMARD4_V q12, q13, q14, q15, q0, q1, q2, q3
  1078. .ifc \satd, satd_
  1079. integrated_satd q4, q8, q9, q10, q11
  1080. integrated_satd q4, q12, q13, q14, q15
  1081. .endif
  1082. SUMSUB_ABCD q0, q8, q1, q9, q8, q12, q9, q13
  1083. SUMSUB_AB q2, q10, q10, q14
  1084. vtrn.16 q8, q9
  1085. SUMSUB_AB q3, q11, q11, q15
  1086. vtrn.16 q0, q1
  1087. SUMSUB_AB q12, q13, q8, q9
  1088. vtrn.16 q10, q11
  1089. SUMSUB_AB q8, q9, q0, q1
  1090. vtrn.16 q2, q3
  1091. SUMSUB_AB q14, q15, q10, q11
  1092. vadd.i16 q10, q2, q3
  1093. vtrn.32 q12, q14
  1094. vsub.i16 q11, q2, q3
  1095. vtrn.32 q13, q15
  1096. SUMSUB_AB q0, q2, q12, q14
  1097. vtrn.32 q8, q10
  1098. SUMSUB_AB q1, q3, q13, q15
  1099. vtrn.32 q9, q11
  1100. SUMSUB_AB q12, q14, q8, q10
  1101. SUMSUB_AB q13, q15, q9, q11
  1102. vswp d1, d24
  1103. ABS2 q0, q12
  1104. vswp d3, d26
  1105. ABS2 q1, q13
  1106. vswp d5, d28
  1107. ABS2 q2, q14
  1108. vswp d7, d30
  1109. ABS2 q3, q15
  1110. vmax.s16 q8, q0, q12
  1111. vmax.s16 q9, q1, q13
  1112. vmax.s16 q10, q2, q14
  1113. vmax.s16 q11, q3, q15
  1114. vadd.i16 q8, q8, q9
  1115. vadd.i16 q9, q10, q11
  1116. .ifc \satd, satd_
  1117. vpadal.u16 q5, q8
  1118. vpadal.u16 q5, q9
  1119. .endif
  1120. bx lr
  1121. endfunc
  1122. .endm
  1123. sa8d_satd_8x8
  1124. sa8d_satd_8x8 satd_
  1125. function pixel_sa8d_satd_16x16_neon
  1126. push {lr}
  1127. vpush {q4-q7}
  1128. vmov.u32 q4, #0
  1129. vmov.u32 q5, #0
  1130. bl sa8d_satd_8x8_neon
  1131. bl sa8d_satd_8x8_neon
  1132. sub r0, r0, r1, lsl #4
  1133. sub r2, r2, r3, lsl #4
  1134. add r0, r0, #8
  1135. add r2, r2, #8
  1136. bl sa8d_satd_8x8_neon
  1137. bl sa8d_satd_8x8_neon
  1138. vadd.u32 d1, d10, d11
  1139. vadd.u32 d0, d8, d9
  1140. vpadd.u32 d1, d1, d1
  1141. vpadd.u32 d0, d0, d0
  1142. vrshr.u32 d1, d1, #1
  1143. vmov.32 r1, d0[0]
  1144. vmov.32 r0, d1[0]
  1145. vpop {q4-q7}
  1146. pop {pc}
  1147. endfunc
  1148. .macro HADAMARD_AC w h
  1149. function pixel_hadamard_ac_\w\()x\h\()_neon
  1150. vpush {d8-d15}
  1151. movrel ip, mask_ac4
  1152. vmov.i8 q4, #0
  1153. // note: this assumes mask_ac8 is after mask_ac4 (so don't move it)
  1154. vld1.64 {d12-d15}, [ip,:128]
  1155. vmov.i8 q5, #0
  1156. mov ip, lr
  1157. bl hadamard_ac_8x8_neon
  1158. .if \h > 8
  1159. bl hadamard_ac_8x8_neon
  1160. .endif
  1161. .if \w > 8
  1162. sub r0, r0, r1, lsl #3
  1163. add r0, r0, #8
  1164. bl hadamard_ac_8x8_neon
  1165. .endif
  1166. .if \w * \h == 256
  1167. sub r0, r0, r1, lsl #4
  1168. bl hadamard_ac_8x8_neon
  1169. .endif
  1170. vadd.s32 d8, d8, d9
  1171. vadd.s32 d10, d10, d11
  1172. vpadd.s32 d0, d8, d10
  1173. vpop {d8-d15}
  1174. mov lr, ip
  1175. vmov r0, r1, d0
  1176. lsr r0, r0, #1
  1177. lsr r1, r1, #2
  1178. bx lr
  1179. endfunc
  1180. .endm
  1181. HADAMARD_AC 8, 8
  1182. HADAMARD_AC 8, 16
  1183. HADAMARD_AC 16, 8
  1184. HADAMARD_AC 16, 16
  1185. // q4: satd q5: sa8d q6: mask_ac4 q7: mask_ac8
  1186. function hadamard_ac_8x8_neon, export=0
  1187. vld1.64 {d2}, [r0,:64], r1
  1188. vld1.64 {d3}, [r0,:64], r1
  1189. vaddl.u8 q0, d2, d3
  1190. vld1.64 {d6}, [r0,:64], r1
  1191. vsubl.u8 q1, d2, d3
  1192. vld1.64 {d7}, [r0,:64], r1
  1193. vaddl.u8 q2, d6, d7
  1194. vld1.64 {d18}, [r0,:64], r1
  1195. vsubl.u8 q3, d6, d7
  1196. vld1.64 {d19}, [r0,:64], r1
  1197. vaddl.u8 q8, d18, d19
  1198. vld1.64 {d22}, [r0,:64], r1
  1199. vsubl.u8 q9, d18, d19
  1200. vld1.64 {d23}, [r0,:64], r1
  1201. SUMSUB_ABCD q12, q14, q13, q15, q0, q2, q1, q3
  1202. vaddl.u8 q10, d22, d23
  1203. vsubl.u8 q11, d22, d23
  1204. vtrn.16 q12, q13
  1205. SUMSUB_ABCD q0, q2, q1, q3, q8, q10, q9, q11
  1206. vtrn.16 q14, q15
  1207. SUMSUB_AB q8, q9, q12, q13
  1208. vtrn.16 q0, q1
  1209. SUMSUB_AB q10, q11, q14, q15
  1210. vtrn.16 q2, q3
  1211. SUMSUB_AB q12, q13, q0, q1
  1212. vtrn.32 q8, q10
  1213. SUMSUB_AB q14, q15, q2, q3
  1214. vtrn.32 q9, q11
  1215. SUMSUB_AB q0, q2, q8, q10
  1216. vtrn.32 q12, q14
  1217. SUMSUB_AB q1, q3, q9, q11
  1218. vtrn.32 q13, q15
  1219. SUMSUB_ABCD q8, q10, q9, q11, q12, q14, q13, q15
  1220. vabs.s16 q12, q0
  1221. vabs.s16 q13, q8
  1222. vabs.s16 q15, q1
  1223. vadd.s16 q12, q12, q13
  1224. vabs.s16 q14, q2
  1225. vand.s16 q12, q12, q6
  1226. vabs.s16 q13, q3
  1227. vadd.s16 q12, q12, q15
  1228. vabs.s16 q15, q9
  1229. vadd.s16 q12, q12, q14
  1230. vabs.s16 q14, q10
  1231. vadd.s16 q12, q12, q13
  1232. vabs.s16 q13, q11
  1233. vadd.s16 q12, q12, q15
  1234. vsub.s16 q15, q11, q3
  1235. vadd.s16 q12, q12, q14
  1236. vadd.s16 q14, q11, q3
  1237. vadd.s16 q12, q12, q13
  1238. vsub.s16 q13, q10, q2
  1239. vadd.s16 q2, q10, q2
  1240. vpadal.u16 q4, q12
  1241. SUMSUB_AB q10, q11, q9, q1
  1242. SUMSUB_AB q9, q8, q0, q8
  1243. vswp d29, d30
  1244. vabs.s16 q14, q14
  1245. vabs.s16 q15, q15
  1246. vswp d5, d26
  1247. vabs.s16 q2, q2
  1248. vabs.s16 q13, q13
  1249. vswp d21, d22
  1250. vabs.s16 q10, q10
  1251. vabs.s16 q11, q11
  1252. vmax.s16 q3, q14, q15
  1253. vmax.s16 q2, q2, q13
  1254. vmax.s16 q1, q10, q11
  1255. vswp d19, d16
  1256. SUMSUB_AB q14, q15, q9, q8
  1257. vadd.s16 q2, q2, q3
  1258. vadd.s16 q2, q2, q1
  1259. vand q14, q14, q7
  1260. vadd.s16 q2, q2, q2
  1261. vabs.s16 q15, q15
  1262. vabs.s16 q14, q14
  1263. vadd.s16 q2, q2, q15
  1264. vadd.s16 q2, q2, q14
  1265. vpadal.u16 q5, q2
  1266. bx lr
  1267. endfunc
  1268. .macro SSIM_ITER n ssa s12 ssb lastssa lasts12 lastssb da db dnext
  1269. vld1.64 {\db}, [r2], r3
  1270. vmull.u8 \ssa, \da, \da
  1271. vmull.u8 \s12, \da, \db
  1272. .if \n == 1
  1273. vpaddl.u16 q2, \lastssa
  1274. vpaddl.u16 q3, \lasts12
  1275. vaddl.u8 q0, d0, \da
  1276. .else
  1277. vpadal.u16 q2, \lastssa
  1278. vpadal.u16 q3, \lasts12
  1279. vaddw.u8 q0, q0, \da
  1280. .endif
  1281. vpadal.u16 q2, \lastssb
  1282. .if \n < 3
  1283. vld1.64 {\dnext}, [r0], r1
  1284. .endif
  1285. .if \n == 1
  1286. vaddl.u8 q1, d2, \db
  1287. .else
  1288. vaddw.u8 q1, q1, \db
  1289. .endif
  1290. vmull.u8 \ssb, \db, \db
  1291. .endm
  1292. function pixel_ssim_4x4x2_core_neon
  1293. ldr ip, [sp]
  1294. vld1.64 {d0}, [r0], r1
  1295. vld1.64 {d2}, [r2], r3
  1296. vmull.u8 q2, d0, d0
  1297. vmull.u8 q3, d0, d2
  1298. vld1.64 {d28}, [r0], r1
  1299. vmull.u8 q15, d2, d2
  1300. SSIM_ITER 1, q8, q9, q14, q2, q3, q15, d28, d29, d26
  1301. SSIM_ITER 2, q10,q11,q13, q8, q9, q14, d26, d27, d28
  1302. SSIM_ITER 3, q8, q9, q15, q10,q11,q13, d28, d29
  1303. vpadal.u16 q2, q8
  1304. vpaddl.u16 q0, q0
  1305. vpaddl.u16 q1, q1
  1306. vpadal.u16 q2, q15
  1307. vpadal.u16 q3, q9
  1308. vpadd.u32 d0, d0, d1
  1309. vpadd.u32 d1, d2, d3
  1310. vpadd.u32 d2, d4, d5
  1311. vpadd.u32 d3, d6, d7
  1312. vst4.32 {d0-d3}, [ip]
  1313. bx lr
  1314. endfunc
  1315. // FIXME: see about doing 16x16 -> 32 bit multiplies for s1/s2
  1316. function pixel_ssim_end4_neon
  1317. vld1.32 {d16-d19}, [r0,:128]!
  1318. vld1.32 {d20-d23}, [r1,:128]!
  1319. vadd.s32 q0, q8, q10
  1320. vadd.s32 q1, q9, q11
  1321. vld1.32 {d24-d27}, [r0,:128]!
  1322. vadd.s32 q0, q0, q1
  1323. vld1.32 {d28-d31}, [r1,:128]!
  1324. vadd.s32 q2, q12, q14
  1325. vadd.s32 q3, q13, q15
  1326. vld1.32 {d16-d17}, [r0,:128]
  1327. vadd.s32 q1, q1, q2
  1328. vld1.32 {d18-d19}, [r1,:128]
  1329. vadd.s32 q8, q8, q9
  1330. vadd.s32 q2, q2, q3
  1331. vadd.s32 q3, q3, q8
  1332. vtrn.32 q0, q1
  1333. vtrn.32 q2, q3
  1334. vswp d1, d4
  1335. vswp d3, d6
  1336. // s1=q0, s2=q1, ss=q2, s12=q3
  1337. vmul.s32 q8, q0, q1 // s1*s2
  1338. vmul.s32 q0, q0, q0
  1339. vmla.s32 q0, q1, q1 // s1*s1 + s2*s2
  1340. vshl.s32 q3, q3, #7
  1341. vshl.s32 q2, q2, #6
  1342. vadd.s32 q1, q8, q8
  1343. mov r3, #416 // ssim_c1 = .01*.01*255*255*64
  1344. movconst ip, 235963 // ssim_c2 = .03*.03*255*255*64*63
  1345. vdup.32 q14, r3
  1346. vdup.32 q15, ip
  1347. vsub.s32 q2, q2, q0 // vars
  1348. vsub.s32 q3, q3, q1 // covar*2
  1349. vadd.s32 q0, q0, q14
  1350. vadd.s32 q2, q2, q15
  1351. vadd.s32 q1, q1, q14
  1352. vadd.s32 q3, q3, q15
  1353. vcvt.f32.s32 q0, q0
  1354. vcvt.f32.s32 q2, q2
  1355. vcvt.f32.s32 q1, q1
  1356. vcvt.f32.s32 q3, q3
  1357. vmul.f32 q0, q0, q2
  1358. vmul.f32 q1, q1, q3
  1359. cmp r2, #4
  1360. vdiv.f32 s0, s4, s0
  1361. vdiv.f32 s1, s5, s1
  1362. vdiv.f32 s2, s6, s2
  1363. vdiv.f32 s3, s7, s3
  1364. beq ssim_skip
  1365. movrel r3, mask_ff
  1366. sub r3, r3, r2, lsl #2
  1367. vld1.64 {d6-d7}, [r3]
  1368. vand q0, q0, q3
  1369. ssim_skip:
  1370. vadd.f32 d0, d0, d1
  1371. vpadd.f32 d0, d0, d0
  1372. vmov.32 r0, d0[0]
  1373. bx lr
  1374. endfunc