intrapred_neon_asm.asm 20.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
;
;  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
;
;  Use of this source code is governed by a BSD-style license
;  that can be found in the LICENSE file in the root of the source
;  tree. An additional intellectual property rights grant can be found
;  in the file PATENTS.  All contributing project authors may
;  be found in the AUTHORS file in the root of the source tree.
;

11 12 13 14 15 16 17 18 19 20 21 22
    EXPORT  |vpx_v_predictor_4x4_neon|
    EXPORT  |vpx_v_predictor_8x8_neon|
    EXPORT  |vpx_v_predictor_16x16_neon|
    EXPORT  |vpx_v_predictor_32x32_neon|
    EXPORT  |vpx_h_predictor_4x4_neon|
    EXPORT  |vpx_h_predictor_8x8_neon|
    EXPORT  |vpx_h_predictor_16x16_neon|
    EXPORT  |vpx_h_predictor_32x32_neon|
    EXPORT  |vpx_tm_predictor_4x4_neon|
    EXPORT  |vpx_tm_predictor_8x8_neon|
    EXPORT  |vpx_tm_predictor_16x16_neon|
    EXPORT  |vpx_tm_predictor_32x32_neon|
23 24 25 26 27 28
    ARM
    REQUIRE8
    PRESERVE8

    AREA ||.text||, CODE, READONLY, ALIGN=2

29
;void vpx_v_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride,
30 31 32 33 34 35 36
;                              const uint8_t *above,
;                              const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

37
|vpx_v_predictor_4x4_neon| PROC
38 39 40 41 42 43
    vld1.32             {d0[0]}, [r2]
    vst1.32             {d0[0]}, [r0], r1
    vst1.32             {d0[0]}, [r0], r1
    vst1.32             {d0[0]}, [r0], r1
    vst1.32             {d0[0]}, [r0], r1
    bx                  lr
44
    ENDP                ; |vpx_v_predictor_4x4_neon|
45

46
;void vpx_v_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride,
47 48 49 50 51 52 53
;                              const uint8_t *above,
;                              const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

54
|vpx_v_predictor_8x8_neon| PROC
55 56 57 58 59 60 61 62 63 64
    vld1.8              {d0}, [r2]
    vst1.8              {d0}, [r0], r1
    vst1.8              {d0}, [r0], r1
    vst1.8              {d0}, [r0], r1
    vst1.8              {d0}, [r0], r1
    vst1.8              {d0}, [r0], r1
    vst1.8              {d0}, [r0], r1
    vst1.8              {d0}, [r0], r1
    vst1.8              {d0}, [r0], r1
    bx                  lr
65
    ENDP                ; |vpx_v_predictor_8x8_neon|
66

67
;void vpx_v_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride,
68 69 70 71 72 73 74
;                                const uint8_t *above,
;                                const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

75
|vpx_v_predictor_16x16_neon| PROC
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
    vld1.8              {q0}, [r2]
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    vst1.8              {q0}, [r0], r1
    bx                  lr
94
    ENDP                ; |vpx_v_predictor_16x16_neon|
95

96
;void vpx_v_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride,
97 98 99 100 101 102 103
;                                const uint8_t *above,
;                                const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

104
|vpx_v_predictor_32x32_neon| PROC
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    vld1.8              {q0, q1}, [r2]
    mov                 r2, #2
loop_v
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    vst1.8              {q0, q1}, [r0], r1
    subs                r2, r2, #1
    bgt                 loop_v
    bx                  lr
127
    ENDP                ; |vpx_v_predictor_32x32_neon|
128

129
;void vpx_h_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride,
130 131 132 133 134 135 136
;                              const uint8_t *above,
;                              const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

137
|vpx_h_predictor_4x4_neon| PROC
138 139 140 141 142 143 144 145 146 147
    vld1.32             {d1[0]}, [r3]
    vdup.8              d0, d1[0]
    vst1.32             {d0[0]}, [r0], r1
    vdup.8              d0, d1[1]
    vst1.32             {d0[0]}, [r0], r1
    vdup.8              d0, d1[2]
    vst1.32             {d0[0]}, [r0], r1
    vdup.8              d0, d1[3]
    vst1.32             {d0[0]}, [r0], r1
    bx                  lr
148
    ENDP                ; |vpx_h_predictor_4x4_neon|
149

150
;void vpx_h_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride,
151 152 153 154 155 156 157
;                              const uint8_t *above,
;                              const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

158
|vpx_h_predictor_8x8_neon| PROC
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
    vld1.64             {d1}, [r3]
    vdup.8              d0, d1[0]
    vst1.64             {d0}, [r0], r1
    vdup.8              d0, d1[1]
    vst1.64             {d0}, [r0], r1
    vdup.8              d0, d1[2]
    vst1.64             {d0}, [r0], r1
    vdup.8              d0, d1[3]
    vst1.64             {d0}, [r0], r1
    vdup.8              d0, d1[4]
    vst1.64             {d0}, [r0], r1
    vdup.8              d0, d1[5]
    vst1.64             {d0}, [r0], r1
    vdup.8              d0, d1[6]
    vst1.64             {d0}, [r0], r1
    vdup.8              d0, d1[7]
    vst1.64             {d0}, [r0], r1
    bx                  lr
177
    ENDP                ; |vpx_h_predictor_8x8_neon|
178

179
;void vpx_h_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride,
180 181 182 183 184 185 186
;                                const uint8_t *above,
;                                const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

187
|vpx_h_predictor_16x16_neon| PROC
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
    vld1.8              {q1}, [r3]
    vdup.8              q0, d2[0]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[1]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[2]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[3]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[4]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[5]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[6]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[7]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[0]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[1]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[2]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[3]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[4]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[5]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[6]
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[7]
    vst1.8              {q0}, [r0], r1
    bx                  lr
222
    ENDP                ; |vpx_h_predictor_16x16_neon|
223

224
;void vpx_h_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride,
225 226 227 228 229 230 231
;                                const uint8_t *above,
;                                const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

232
|vpx_h_predictor_32x32_neon| PROC
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
    sub                 r1, r1, #16
    mov                 r2, #2
loop_h
    vld1.8              {q1}, [r3]!
    vdup.8              q0, d2[0]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[1]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[2]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[3]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[4]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[5]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[6]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d2[7]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[0]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[1]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[2]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[3]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[4]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[5]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[6]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    vdup.8              q0, d3[7]
    vst1.8              {q0}, [r0]!
    vst1.8              {q0}, [r0], r1
    subs                r2, r2, #1
    bgt                 loop_h
    bx                  lr
288
    ENDP                ; |vpx_h_predictor_32x32_neon|
289

290
;void vpx_tm_predictor_4x4_neon (uint8_t *dst, ptrdiff_t y_stride,
291 292 293 294 295 296 297
;                                const uint8_t *above,
;                                const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

298
|vpx_tm_predictor_4x4_neon| PROC
299 300
    ; Load ytop_left = above[-1];
    sub                 r12, r2, #1
301
    vld1.u8             {d0[]}, [r12]
302 303 304 305 306 307 308 309 310

    ; Load above 4 pixels
    vld1.32             {d2[0]}, [r2]

    ; Compute above - ytop_left
    vsubl.u8            q3, d2, d0

    ; Load left row by row and compute left + (above - ytop_left)
    ; 1st row and 2nd row
311 312 313 314
    vld1.u8             {d2[]}, [r3]!
    vld1.u8             {d4[]}, [r3]!
    vmovl.u8            q1, d2
    vmovl.u8            q2, d4
315 316
    vadd.s16            q1, q1, q3
    vadd.s16            q2, q2, q3
317 318
    vqmovun.s16         d0, q1
    vqmovun.s16         d1, q2
319 320 321 322
    vst1.32             {d0[0]}, [r0], r1
    vst1.32             {d1[0]}, [r0], r1

    ; 3rd row and 4th row
323 324 325 326
    vld1.u8             {d2[]}, [r3]!
    vld1.u8             {d4[]}, [r3]
    vmovl.u8            q1, d2
    vmovl.u8            q2, d4
327 328
    vadd.s16            q1, q1, q3
    vadd.s16            q2, q2, q3
329 330
    vqmovun.s16         d0, q1
    vqmovun.s16         d1, q2
331 332 333
    vst1.32             {d0[0]}, [r0], r1
    vst1.32             {d1[0]}, [r0], r1
    bx                  lr
334
    ENDP                ; |vpx_tm_predictor_4x4_neon|
335

336
;void vpx_tm_predictor_8x8_neon (uint8_t *dst, ptrdiff_t y_stride,
337 338 339 340 341 342 343
;                                const uint8_t *above,
;                                const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

344
|vpx_tm_predictor_8x8_neon| PROC
345 346
    ; Load ytop_left = above[-1];
    sub                 r12, r2, #1
347
    vld1.8              {d0[]}, [r12]
348

hkuang's avatar
hkuang committed
349
    ; preload 8 left
350
    vld1.8              {d30}, [r3]
hkuang's avatar
hkuang committed
351

352 353 354
    ; Load above 8 pixels
    vld1.64             {d2}, [r2]

hkuang's avatar
hkuang committed
355 356
    vmovl.u8            q10, d30

357 358 359 360 361
    ; Compute above - ytop_left
    vsubl.u8            q3, d2, d0

    ; Load left row by row and compute left + (above - ytop_left)
    ; 1st row and 2nd row
hkuang's avatar
hkuang committed
362 363 364 365
    vdup.16             q0, d20[0]
    vdup.16             q1, d20[1]
    vadd.s16            q0, q3, q0
    vadd.s16            q1, q3, q1
366 367

    ; 3rd row and 4th row
hkuang's avatar
hkuang committed
368 369 370 371
    vdup.16             q8, d20[2]
    vdup.16             q9, d20[3]
    vadd.s16            q8, q3, q8
    vadd.s16            q9, q3, q9
372

373 374 375 376
    vqmovun.s16         d0, q0
    vqmovun.s16         d1, q1
    vqmovun.s16         d2, q8
    vqmovun.s16         d3, q9
377

378 379
    vst1.64             {d0}, [r0], r1
    vst1.64             {d1}, [r0], r1
380 381
    vst1.64             {d2}, [r0], r1
    vst1.64             {d3}, [r0], r1
382 383

    ; 5th row and 6th row
hkuang's avatar
hkuang committed
384 385 386 387 388 389 390 391 392 393 394
    vdup.16             q0, d21[0]
    vdup.16             q1, d21[1]
    vadd.s16            q0, q3, q0
    vadd.s16            q1, q3, q1

    ; 7th row and 8th row
    vdup.16             q8, d21[2]
    vdup.16             q9, d21[3]
    vadd.s16            q8, q3, q8
    vadd.s16            q9, q3, q9

395 396 397 398
    vqmovun.s16         d0, q0
    vqmovun.s16         d1, q1
    vqmovun.s16         d2, q8
    vqmovun.s16         d3, q9
399

400 401
    vst1.64             {d0}, [r0], r1
    vst1.64             {d1}, [r0], r1
402 403 404
    vst1.64             {d2}, [r0], r1
    vst1.64             {d3}, [r0], r1

405
    bx                  lr
406
    ENDP                ; |vpx_tm_predictor_8x8_neon|
407

408
;void vpx_tm_predictor_16x16_neon (uint8_t *dst, ptrdiff_t y_stride,
409 410 411 412 413 414 415
;                                const uint8_t *above,
;                                const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

416
|vpx_tm_predictor_16x16_neon| PROC
417 418
    ; Load ytop_left = above[-1];
    sub                 r12, r2, #1
419
    vld1.8              {d0[]}, [r12]
420 421

    ; Load above 8 pixels
422
    vld1.8              {q1}, [r2]
423 424

    ; preload 8 left into r12
425
    vld1.8              {d18}, [r3]!
426 427 428

    ; Compute above - ytop_left
    vsubl.u8            q2, d2, d0
429
    vsubl.u8            q3, d3, d0
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444

    vmovl.u8            q10, d18

    ; Load left row by row and compute left + (above - ytop_left)
    ; Process 8 rows in each single loop and loop 2 times to process 16 rows.
    mov                 r2, #2

loop_16x16_neon
    ; Process two rows.
    vdup.16             q0, d20[0]
    vdup.16             q8, d20[1]
    vadd.s16            q1, q0, q2
    vadd.s16            q0, q0, q3
    vadd.s16            q11, q8, q2
    vadd.s16            q8, q8, q3
445 446 447 448
    vqmovun.s16         d2, q1
    vqmovun.s16         d3, q0
    vqmovun.s16         d22, q11
    vqmovun.s16         d23, q8
449 450 451 452 453 454 455 456 457 458
    vdup.16             q0, d20[2]                  ; proload next 2 rows data
    vdup.16             q8, d20[3]
    vst1.64             {d2,d3}, [r0], r1
    vst1.64             {d22,d23}, [r0], r1

    ; Process two rows.
    vadd.s16            q1, q0, q2
    vadd.s16            q0, q0, q3
    vadd.s16            q11, q8, q2
    vadd.s16            q8, q8, q3
459 460 461 462
    vqmovun.s16         d2, q1
    vqmovun.s16         d3, q0
    vqmovun.s16         d22, q11
    vqmovun.s16         d23, q8
463 464 465 466 467 468 469 470 471
    vdup.16             q0, d21[0]                  ; proload next 2 rows data
    vdup.16             q8, d21[1]
    vst1.64             {d2,d3}, [r0], r1
    vst1.64             {d22,d23}, [r0], r1

    vadd.s16            q1, q0, q2
    vadd.s16            q0, q0, q3
    vadd.s16            q11, q8, q2
    vadd.s16            q8, q8, q3
472 473 474 475
    vqmovun.s16         d2, q1
    vqmovun.s16         d3, q0
    vqmovun.s16         d22, q11
    vqmovun.s16         d23, q8
476 477 478 479 480 481 482 483 484 485
    vdup.16             q0, d21[2]                  ; proload next 2 rows data
    vdup.16             q8, d21[3]
    vst1.64             {d2,d3}, [r0], r1
    vst1.64             {d22,d23}, [r0], r1


    vadd.s16            q1, q0, q2
    vadd.s16            q0, q0, q3
    vadd.s16            q11, q8, q2
    vadd.s16            q8, q8, q3
486 487 488 489
    vqmovun.s16         d2, q1
    vqmovun.s16         d3, q0
    vqmovun.s16         d22, q11
    vqmovun.s16         d23, q8
490
    vld1.8              {d18}, [r3]!                  ; preload 8 left into r12
491 492 493 494 495 496 497 498
    vmovl.u8            q10, d18
    vst1.64             {d2,d3}, [r0], r1
    vst1.64             {d22,d23}, [r0], r1

    subs                r2, r2, #1
    bgt                 loop_16x16_neon

    bx                  lr
499
    ENDP                ; |vpx_tm_predictor_16x16_neon|
500

501
;void vpx_tm_predictor_32x32_neon (uint8_t *dst, ptrdiff_t y_stride,
502 503 504 505 506 507 508
;                                  const uint8_t *above,
;                                  const uint8_t *left)
; r0  uint8_t *dst
; r1  ptrdiff_t y_stride
; r2  const uint8_t *above
; r3  const uint8_t *left

509
|vpx_tm_predictor_32x32_neon| PROC
510 511
    ; Load ytop_left = above[-1];
    sub                 r12, r2, #1
512
    vld1.8              {d0[]}, [r12]
513 514

    ; Load above 32 pixels
515 516
    vld1.8              {q1}, [r2]!
    vld1.8              {q2}, [r2]
517 518

    ; preload 8 left pixels
519
    vld1.8              {d26}, [r3]!
520 521 522

    ; Compute above - ytop_left
    vsubl.u8            q8, d2, d0
523
    vsubl.u8            q9, d3, d0
524
    vsubl.u8            q10, d4, d0
525
    vsubl.u8            q11, d5, d0
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540

    vmovl.u8            q3, d26

    ; Load left row by row and compute left + (above - ytop_left)
    ; Process 8 rows in each single loop and loop 4 times to process 32 rows.
    mov                 r2, #4

loop_32x32_neon
    ; Process two rows.
    vdup.16             q0, d6[0]
    vdup.16             q2, d6[1]
    vadd.s16            q12, q0, q8
    vadd.s16            q13, q0, q9
    vadd.s16            q14, q0, q10
    vadd.s16            q15, q0, q11
541 542
    vqmovun.s16         d0, q12
    vqmovun.s16         d1, q13
543 544
    vadd.s16            q12, q2, q8
    vadd.s16            q13, q2, q9
545 546
    vqmovun.s16         d2, q14
    vqmovun.s16         d3, q15
547 548 549
    vadd.s16            q14, q2, q10
    vadd.s16            q15, q2, q11
    vst1.64             {d0-d3}, [r0], r1
550 551 552 553
    vqmovun.s16         d24, q12
    vqmovun.s16         d25, q13
    vqmovun.s16         d26, q14
    vqmovun.s16         d27, q15
554 555 556 557 558 559 560 561 562
    vdup.16             q1, d6[2]
    vdup.16             q2, d6[3]
    vst1.64             {d24-d27}, [r0], r1

    ; Process two rows.
    vadd.s16            q12, q1, q8
    vadd.s16            q13, q1, q9
    vadd.s16            q14, q1, q10
    vadd.s16            q15, q1, q11
563 564
    vqmovun.s16         d0, q12
    vqmovun.s16         d1, q13
565 566
    vadd.s16            q12, q2, q8
    vadd.s16            q13, q2, q9
567 568
    vqmovun.s16         d2, q14
    vqmovun.s16         d3, q15
569 570 571
    vadd.s16            q14, q2, q10
    vadd.s16            q15, q2, q11
    vst1.64             {d0-d3}, [r0], r1
572 573 574 575
    vqmovun.s16         d24, q12
    vqmovun.s16         d25, q13
    vqmovun.s16         d26, q14
    vqmovun.s16         d27, q15
576 577 578 579 580 581 582 583 584
    vdup.16             q0, d7[0]
    vdup.16             q2, d7[1]
    vst1.64             {d24-d27}, [r0], r1

    ; Process two rows.
    vadd.s16            q12, q0, q8
    vadd.s16            q13, q0, q9
    vadd.s16            q14, q0, q10
    vadd.s16            q15, q0, q11
585 586
    vqmovun.s16         d0, q12
    vqmovun.s16         d1, q13
587 588
    vadd.s16            q12, q2, q8
    vadd.s16            q13, q2, q9
589 590
    vqmovun.s16         d2, q14
    vqmovun.s16         d3, q15
591 592 593
    vadd.s16            q14, q2, q10
    vadd.s16            q15, q2, q11
    vst1.64             {d0-d3}, [r0], r1
594 595 596 597
    vqmovun.s16         d24, q12
    vqmovun.s16         d25, q13
    vqmovun.s16         d26, q14
    vqmovun.s16         d27, q15
598 599 600 601 602 603 604 605 606
    vdup.16             q0, d7[2]
    vdup.16             q2, d7[3]
    vst1.64             {d24-d27}, [r0], r1

    ; Process two rows.
    vadd.s16            q12, q0, q8
    vadd.s16            q13, q0, q9
    vadd.s16            q14, q0, q10
    vadd.s16            q15, q0, q11
607 608
    vqmovun.s16         d0, q12
    vqmovun.s16         d1, q13
609 610
    vadd.s16            q12, q2, q8
    vadd.s16            q13, q2, q9
611 612
    vqmovun.s16         d2, q14
    vqmovun.s16         d3, q15
613 614 615
    vadd.s16            q14, q2, q10
    vadd.s16            q15, q2, q11
    vst1.64             {d0-d3}, [r0], r1
616 617
    vqmovun.s16         d24, q12
    vqmovun.s16         d25, q13
618
    vld1.8              {d0}, [r3]!                   ; preload 8 left pixels
619 620
    vqmovun.s16         d26, q14
    vqmovun.s16         d27, q15
621 622 623 624 625 626 627
    vmovl.u8            q3, d0
    vst1.64             {d24-d27}, [r0], r1

    subs                r2, r2, #1
    bgt                 loop_32x32_neon

    bx                  lr
628
    ENDP                ; |vpx_tm_predictor_32x32_neon|
629

630
    END