[x265] [PATCH] arm: Implement sad_x3 and sad_x4 ARM NEON asm

dnyaneshwar at multicorewareinc.com dnyaneshwar at multicorewareinc.com
Tue Feb 16 06:04:17 CET 2016


# HG changeset patch
# User Dnyaneshwar G <dnyaneshwar at multicorewareinc.com>
# Date 1455598958 -19800
#      Tue Feb 16 10:32:38 2016 +0530
# Node ID ac6c535109a43e9cdb69f30db1143c06400a19f4
# Parent  e3902c96c3c268ec4ab1a4976ee2feae7348b36f
arm: Implement sad_x3 and sad_x4 ARM NEON asm

diff -r e3902c96c3c2 -r ac6c535109a4 source/common/arm/asm-primitives.cpp
--- a/source/common/arm/asm-primitives.cpp	Thu Feb 11 15:00:20 2016 +0530
+++ b/source/common/arm/asm-primitives.cpp	Tue Feb 16 10:32:38 2016 +0530
@@ -41,6 +41,7 @@
 {
     if (cpuMask & X265_CPU_NEON)
     {
+        // blockcopy
         p.pu[LUMA_16x16].copy_pp = PFX(blockcopy_pp_16x16_neon);
         p.pu[LUMA_8x4].copy_pp = PFX(blockcopy_pp_8x4_neon);
         p.pu[LUMA_8x8].copy_pp = PFX(blockcopy_pp_8x8_neon);
@@ -66,11 +67,65 @@
         p.pu[LUMA_64x32].copy_pp = PFX(blockcopy_pp_64x32_neon);
         p.pu[LUMA_64x48].copy_pp = PFX(blockcopy_pp_64x48_neon);
         p.pu[LUMA_64x64].copy_pp = PFX(blockcopy_pp_64x64_neon);
+
+        // sad_x3
+        p.pu[LUMA_4x4].sad_x3   = PFX(sad_x3_4x4_neon);
+        p.pu[LUMA_4x8].sad_x3   = PFX(sad_x3_4x8_neon);
+        p.pu[LUMA_4x16].sad_x3  = PFX(sad_x3_4x16_neon);
+        p.pu[LUMA_8x4].sad_x3   = PFX(sad_x3_8x4_neon);
+        p.pu[LUMA_8x8].sad_x3   = PFX(sad_x3_8x8_neon);
+        p.pu[LUMA_8x16].sad_x3  = PFX(sad_x3_8x16_neon);
+        p.pu[LUMA_8x32].sad_x3  = PFX(sad_x3_8x32_neon);
+        p.pu[LUMA_12x16].sad_x3 = PFX(sad_x3_12x16_neon);
+        p.pu[LUMA_16x4].sad_x3  = PFX(sad_x3_16x4_neon);
+        p.pu[LUMA_16x8].sad_x3  = PFX(sad_x3_16x8_neon);
+        p.pu[LUMA_16x12].sad_x3 = PFX(sad_x3_16x12_neon);
+        p.pu[LUMA_16x16].sad_x3 = PFX(sad_x3_16x16_neon);
+        p.pu[LUMA_16x32].sad_x3 = PFX(sad_x3_16x32_neon);
+        p.pu[LUMA_16x64].sad_x3 = PFX(sad_x3_16x64_neon);
+        p.pu[LUMA_24x32].sad_x3 = PFX(sad_x3_24x32_neon);
+        p.pu[LUMA_32x8].sad_x3  = PFX(sad_x3_32x8_neon);
+        p.pu[LUMA_32x16].sad_x3 = PFX(sad_x3_32x16_neon);
+        p.pu[LUMA_32x24].sad_x3 = PFX(sad_x3_32x24_neon);
+        p.pu[LUMA_32x32].sad_x3 = PFX(sad_x3_32x32_neon);
+        p.pu[LUMA_32x64].sad_x3 = PFX(sad_x3_32x64_neon);
+        p.pu[LUMA_48x64].sad_x3 = PFX(sad_x3_48x64_neon);
+        p.pu[LUMA_64x16].sad_x3 = PFX(sad_x3_64x16_neon);
+        p.pu[LUMA_64x32].sad_x3 = PFX(sad_x3_64x32_neon);
+        p.pu[LUMA_64x48].sad_x3 = PFX(sad_x3_64x48_neon);
+        p.pu[LUMA_64x64].sad_x3 = PFX(sad_x3_64x64_neon);
+
+        // sad_x4
+        p.pu[LUMA_4x4].sad_x4   = PFX(sad_x4_4x4_neon);
+        p.pu[LUMA_4x8].sad_x4   = PFX(sad_x4_4x8_neon);
+        p.pu[LUMA_4x16].sad_x4  = PFX(sad_x4_4x16_neon);
+        p.pu[LUMA_8x4].sad_x4   = PFX(sad_x4_8x4_neon);
+        p.pu[LUMA_8x8].sad_x4   = PFX(sad_x4_8x8_neon);
+        p.pu[LUMA_8x16].sad_x4  = PFX(sad_x4_8x16_neon);
+        p.pu[LUMA_8x32].sad_x4  = PFX(sad_x4_8x32_neon);
+        p.pu[LUMA_12x16].sad_x4 = PFX(sad_x4_12x16_neon);
+        p.pu[LUMA_16x4].sad_x4  = PFX(sad_x4_16x4_neon);
+        p.pu[LUMA_16x8].sad_x4  = PFX(sad_x4_16x8_neon);
+        p.pu[LUMA_16x12].sad_x4 = PFX(sad_x4_16x12_neon);
+        p.pu[LUMA_16x16].sad_x4 = PFX(sad_x4_16x16_neon);
+        p.pu[LUMA_16x32].sad_x4 = PFX(sad_x4_16x32_neon);
+        p.pu[LUMA_16x64].sad_x4 = PFX(sad_x4_16x64_neon);
+        p.pu[LUMA_24x32].sad_x4 = PFX(sad_x4_24x32_neon);
+        p.pu[LUMA_32x8].sad_x4  = PFX(sad_x4_32x8_neon);
+        p.pu[LUMA_32x16].sad_x4 = PFX(sad_x4_32x16_neon);
+        p.pu[LUMA_32x24].sad_x4 = PFX(sad_x4_32x24_neon);
+        p.pu[LUMA_32x32].sad_x4 = PFX(sad_x4_32x32_neon);
+        p.pu[LUMA_32x64].sad_x4 = PFX(sad_x4_32x64_neon);
+        p.pu[LUMA_48x64].sad_x4 = PFX(sad_x4_48x64_neon);
+        p.pu[LUMA_64x16].sad_x4 = PFX(sad_x4_64x16_neon);
+        p.pu[LUMA_64x32].sad_x4 = PFX(sad_x4_64x32_neon);
+        p.pu[LUMA_64x48].sad_x4 = PFX(sad_x4_64x48_neon);
+        p.pu[LUMA_64x64].sad_x4 = PFX(sad_x4_64x64_neon);
     }
     if (cpuMask & X265_CPU_ARMV6)
     {
-	 p.pu[LUMA_4x4].sad=PFX(pixel_sad_4x4_armv6);
-         p.pu[LUMA_4x8].sad=PFX(pixel_sad_4x8_armv6);
+        p.pu[LUMA_4x4].sad = PFX(pixel_sad_4x4_armv6);
+        p.pu[LUMA_4x8].sad = PFX(pixel_sad_4x8_armv6);
     }
 }
 } // namespace X265_NS
diff -r e3902c96c3c2 -r ac6c535109a4 source/common/arm/asm.S
--- a/source/common/arm/asm.S	Thu Feb 11 15:00:20 2016 +0530
+++ b/source/common/arm/asm.S	Tue Feb 16 10:32:38 2016 +0530
@@ -108,7 +108,7 @@
 #define JOIN(a, b) GLUE(a, b)
 #define X(s) JOIN(EXTERN_ASM, s)
 
-#define FENC_STRIDE 16
+#define FENC_STRIDE 64
 #define FDEC_STRIDE 32
 
 .macro HORIZ_ADD dest, a, b
diff -r e3902c96c3c2 -r ac6c535109a4 source/common/arm/mc-a.S
--- a/source/common/arm/mc-a.S	Thu Feb 11 15:00:20 2016 +0530
+++ b/source/common/arm/mc-a.S	Tue Feb 16 10:32:38 2016 +0530
@@ -34,7 +34,7 @@
  * r0   - dst
  * r1   - dstStride
  * r2   - src
- * d3   - srcStride */
+ * r3   - srcStride */
 function x265_blockcopy_pp_16x16_neon
     vld1.8          {q0}, [r2]
     vst1.8          {q0}, [r0]
diff -r e3902c96c3c2 -r ac6c535109a4 source/common/arm/pixel.h
--- a/source/common/arm/pixel.h	Thu Feb 11 15:00:20 2016 +0530
+++ b/source/common/arm/pixel.h	Tue Feb 16 10:32:38 2016 +0530
@@ -7,7 +7,7 @@
  * Authors: Laurent Aimar <fenrir at via.ecp.fr>
  *          Loren Merritt <lorenm at u.washington.edu>
  *          Fiona Glaser <fiona at x264.com>
-;*          Min Chen <chenm003 at 163.com>
+ *          Min Chen <chenm003 at 163.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,6 +29,60 @@
 
 #ifndef X265_I386_PIXEL_ARM_H
 #define X265_I386_PIXEL_ARM_H
+
 int x265_pixel_sad_4x4_armv6(const pixel* dst, intptr_t dstStride, const pixel* src, intptr_t srcStride);
 int x265_pixel_sad_4x8_armv6(const pixel* dst, intptr_t dstStride, const pixel* src, intptr_t srcStride);
+
+void x265_sad_x3_4x4_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_4x8_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_4x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_8x4_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_8x8_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_8x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_8x32_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_12x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_16x4_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_16x8_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_16x12_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_16x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_16x32_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_16x64_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_24x32_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_32x8_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_32x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_32x24_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_32x32_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_32x64_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_48x64_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_64x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_64x32_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_64x48_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+void x265_sad_x3_64x64_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);
+
+void x265_sad_x4_4x4_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_4x8_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_4x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_8x4_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_8x8_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_8x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_8x32_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_12x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_16x4_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_16x8_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_16x12_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_16x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_16x32_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_16x64_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_24x32_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_32x8_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_32x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_32x24_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_32x32_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_32x64_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_48x64_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_64x16_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_64x32_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_64x48_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+void x265_sad_x4_64x64_neon(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);
+
 #endif // ifndef X265_I386_PIXEL_ARM_H
diff -r e3902c96c3c2 -r ac6c535109a4 source/common/arm/sad-a.S
--- a/source/common/arm/sad-a.S	Thu Feb 11 15:00:20 2016 +0530
+++ b/source/common/arm/sad-a.S	Tue Feb 16 10:32:38 2016 +0530
@@ -1,8 +1,9 @@
 /*****************************************************************************
  * Copyright (C) 2016 x265 project
  *
- * Authors:David Conrad <lessen42 at gmail.com>
+ * Authors: David Conrad <lessen42 at gmail.com>
  *          Janne Grunau <janne-x264 at jannau.net>
+ *          Dnyaneshwar G <dnyaneshwar at multicorewareinc.com>
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,6 +28,8 @@
 .section .rodata
 
 .align 4
+sad12_mask:
+.byte 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0
 
 .text
 
@@ -35,7 +38,7 @@
  * r0   - dst
  * r1   - dstStride
  * r2   - src
- * d3   - srcStride */
+ * r3   - srcStride */
 
 .macro SAD4_ARMV6 h
 function x265_pixel_sad_4x\h\()_armv6
@@ -61,3 +64,968 @@
 SAD4_ARMV6 4
 SAD4_ARMV6 8
 
+// SAD_X3 and SAD_X4 code start
+
+.macro SAD_X_START_4 x
+    vld1.32         {d0[]}, [r0], r12
+    vld1.32         {d1[]}, [r1], r4
+    vld1.32         {d2[]}, [r2], r4
+    vld1.32         {d3[]}, [r3], r4
+.if \x == 4
+    vld1.32         {d4[]}, [lr], r4
+.endif
+    vabdl.u8        q8, d0, d1
+    vabdl.u8        q9, d0, d2
+    vabdl.u8        q10, d0, d3
+.if \x == 4
+    vabdl.u8        q11, d0, d4
+.endif
+.endm
+
+.macro SAD_X_4 x
+    vld1.32         {d0[]}, [r0], r12
+    vld1.32         {d1[]}, [r1], r4
+    vld1.32         {d2[]}, [r2], r4
+    vld1.32         {d3[]}, [r3], r4
+.if \x == 4
+    vld1.32         {d4[]}, [lr], r4
+.endif
+    vabal.u8        q8, d0, d1
+    vabal.u8        q9, d0, d2
+    vabal.u8        q10, d0, d3
+.if \x == 4
+    vabal.u8        q11, d0, d4
+.endif
+.endm
+
+.macro SAD_X_4xN x, h
+function x265_sad_x\x\()_4x\h\()_neon
+    push            {r4, r5, lr}
+.if \x == 3
+    ldrd            r4, r5, [sp, #12]
+.else
+    ldr             lr, [sp, #12]
+    ldrd            r4, r5, [sp, #16]
+.endif
+    mov             r12, #FENC_STRIDE
+
+    SAD_X_START_4 \x
+.rept \h - 1
+    SAD_X_4 \x 
+.endr
+    vpadd.u16       d0, d16, d18
+    vpadd.u16       d1, d20, d22
+    vpaddl.u16      q0, q0
+.if \x == 3
+    vst1.32         {d0}, [r5]!
+    vst1.32         {d1[0]}, [r5, :32]
+.else
+    vst1.32         {d0-d1}, [r5]
+.endif
+    pop             {r4, r5, lr}
+    bx              lr
+endfunc
+.endm
+
+SAD_X_4xN 3 4
+SAD_X_4xN 3 8
+SAD_X_4xN 3 16
+
+SAD_X_4xN 4 4
+SAD_X_4xN 4 8
+SAD_X_4xN 4 16
+
+.macro SAD_X_START_8 x
+    vld1.8          {d0}, [r0], r12
+    vld1.8          {d1}, [r1], r4
+    vld1.8          {d2}, [r2], r4
+    vld1.8          {d3}, [r3], r4
+.if \x == 4
+    vld1.8          {d4}, [lr], r4
+.endif
+    vabdl.u8        q8, d0, d1
+    vabdl.u8        q9, d0, d2
+    vabdl.u8        q10, d0, d3
+.if \x == 4
+    vabdl.u8        q11, d0, d4
+.endif
+.endm
+
+.macro SAD_X_8 x
+    vld1.8          {d0}, [r0], r12
+    vld1.8          {d1}, [r1], r4
+    vld1.8          {d2}, [r2], r4
+    vld1.8          {d3}, [r3], r4
+.if \x == 4
+    vld1.8          {d4}, [lr], r4
+.endif
+    vabal.u8        q8, d0, d1
+    vabal.u8        q9, d0, d2
+    vabal.u8        q10, d0, d3
+.if \x == 4
+    vabal.u8        q11, d0, d4
+.endif
+.endm
+
+.macro SAD_X_8xN x, h
+function x265_sad_x\x\()_8x\h\()_neon
+    push            {r4, r5, lr}
+.if \x == 3
+    ldrd            r4, r5, [sp, #12]
+.else
+    ldr             lr, [sp, #12]
+    ldrd            r4, r5, [sp, #16]
+.endif
+    mov             r12, #FENC_STRIDE
+    SAD_X_START_8 \x
+.rept \h - 1
+    SAD_X_8 \x
+.endr
+    vadd.u16        d16, d16, d17
+    vadd.u16        d18, d18, d19
+    vadd.u16        d20, d20, d21
+    vadd.u16        d22, d22, d23
+
+    vpadd.u16       d0, d16, d18
+    vpadd.u16       d1, d20, d22
+    vpaddl.u16      q0, q0
+.if \x == 3
+    vst1.32         {d0}, [r5]!
+    vst1.32         {d1[0]}, [r5, :32]
+.else
+    vst1.32         {d0-d1}, [r5]
+.endif
+    pop             {r4, r5, lr}
+    bx              lr
+endfunc
+.endm
+
+SAD_X_8xN 3 4
+SAD_X_8xN 3 8
+SAD_X_8xN 3 16
+SAD_X_8xN 3 32
+
+SAD_X_8xN 4 4
+SAD_X_8xN 4 8
+SAD_X_8xN 4 16
+SAD_X_8xN 4 32
+
+.macro SAD_X_START_16 x
+    vld1.8          {q0}, [r0], r12
+    vld1.8          {q1}, [r1], r4
+    vld1.8          {q2}, [r2], r4
+    vld1.8          {q3}, [r3], r4
+    vabdl.u8        q8, d0, d2
+    vabdl.u8        q9, d1, d3
+    vabdl.u8        q10, d0, d4
+    vabdl.u8        q11, d1, d5
+    vabdl.u8        q12, d0, d6
+    vabdl.u8        q13, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr], r4
+    vabdl.u8        q14, d0, d6
+    vabdl.u8        q15, d1, d7 
+.endif
+.endm
+
+.macro SAD_X_16 x
+    vld1.8          {q0}, [r0], r12
+    vld1.8          {q1}, [r1], r4
+    vld1.8          {q2}, [r2], r4
+    vld1.8          {q3}, [r3], r4
+    vabal.u8        q8, d0, d2
+    vabal.u8        q9, d1, d3
+    vabal.u8        q10, d0, d4
+    vabal.u8        q11, d1, d5
+    vabal.u8        q12, d0, d6
+    vabal.u8        q13, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr], r4
+    vabal.u8        q14, d0, d6
+    vabal.u8        q15, d1, d7
+.endif
+.endm
+
+.macro SAD_X_16xN x, h
+function x265_sad_x\x\()_16x\h\()_neon
+    push            {r4, r5, lr}
+.if \x == 3
+    ldrd            r4, r5, [sp, #12]
+.else
+    ldr             lr, [sp, #12]
+    ldrd            r4, r5, [sp, #16]
+.endif
+    mov             r12, #FENC_STRIDE
+    SAD_X_START_16 \x
+.rept \h - 1
+    SAD_X_16 \x
+.endr
+    vadd.u16        q8, q8, q9
+    vadd.u16        q10, q10, q11
+    vadd.u16        q12, q12, q13
+.if \x == 4
+    vadd.u16        q14, q14, q15
+.endif
+    vadd.u16        d16, d16, d17
+    vadd.u16        d20, d20, d21
+    vadd.u16        d24, d24, d25
+.if \x == 4
+    vadd.u16        d28, d28, d29
+.endif
+
+.if \h <= 32
+    vpadd.u16       d0, d16, d20
+    vpadd.u16       d1, d24, d28
+    vpaddl.u16      q0, q0
+  .if \x == 3
+    vst1.32         {d0}, [r5]!
+    vst1.32         {d1[0]}, [r5, :32]
+  .else
+    vst1.32         {d0-d1}, [r5]
+  .endif
+.else
+    vpaddl.u16      d16, d16
+    vpaddl.u16      d20, d20
+    vpaddl.u16      d24, d24
+  .if \x == 4
+    vpaddl.u16      d28, d28
+  .endif
+    vpaddl.u32      d16, d16
+    vpaddl.u32      d20, d20
+    vpaddl.u32      d24, d24
+  .if \x == 4
+    vpaddl.u32      d28, d28
+  .endif
+    vst1.32         {d16[0]}, [r5]!
+    vst1.32         {d20[0]}, [r5]!
+  .if \x == 3
+    vst1.32         {d24[0]}, [r5]
+  .endif
+  .if \x == 4
+    vst1.32         {d24[0]}, [r5]!
+    vst1.32         {d28[0]}, [r5]
+  .endif
+.endif
+    pop             {r4, r5, lr}
+    bx              lr
+endfunc
+.endm
+
+SAD_X_16xN 3 4
+SAD_X_16xN 3 12
+
+SAD_X_16xN 4 4
+SAD_X_16xN 4 12
+
+.macro SAD_X_16xN_LOOP x, h
+function x265_sad_x\x\()_16x\h\()_neon
+    push            {r4-r6, lr}
+.if \x == 3
+    ldrd            r4, r5, [sp, #16]
+.else
+    ldr             lr, [sp, #16]
+    ldrd            r4, r5, [sp, #20]
+.endif
+    mov             r12, #FENC_STRIDE
+    mov             r6, #\h/8
+    veor.u8         q8, q8
+    veor.u8         q9, q9
+    veor.u8         q10, q10
+    veor.u8         q11, q11
+    veor.u8         q12, q12
+    veor.u8         q13, q13
+.if \x == 4
+    veor.u8         q14, q14
+    veor.u8         q15, q15
+.endif
+
+.loop_sad_x\x\()_16x\h:
+.rept 8
+    SAD_X_16 \x
+.endr
+    subs            r6, #1
+    bne             .loop_sad_x\x\()_16x\h
+
+    vadd.u16        q8, q8, q9
+    vadd.u16        q10, q10, q11
+    vadd.u16        q12, q12, q13
+.if \x == 4
+    vadd.u16        q14, q14, q15
+.endif
+    vadd.u16        d16, d16, d17
+    vadd.u16        d20, d20, d21
+    vadd.u16        d24, d24, d25
+.if \x == 4
+    vadd.u16        d28, d28, d29
+.endif
+
+.if \h <= 32
+    vpadd.u16       d0, d16, d20
+    vpadd.u16       d1, d24, d28
+    vpaddl.u16      q0, q0
+  .if \x == 3
+    vst1.32         {d0}, [r5]!
+    vst1.32         {d1[0]}, [r5, :32]
+  .else
+    vst1.32         {d0-d1}, [r5]
+  .endif
+.else
+    vpaddl.u16      d16, d16
+    vpaddl.u16      d20, d20
+    vpaddl.u16      d24, d24
+  .if \x == 4
+    vpaddl.u16      d28, d28
+  .endif
+    vpaddl.u32      d16, d16
+    vpaddl.u32      d20, d20
+    vpaddl.u32      d24, d24
+  .if \x == 4
+    vpaddl.u32      d28, d28
+  .endif
+    vst1.32         {d16[0]}, [r5]!
+    vst1.32         {d20[0]}, [r5]!
+  .if \x == 3
+    vst1.32         {d24[0]}, [r5]
+  .endif
+  .if \x == 4
+    vst1.32         {d24[0]}, [r5]!
+    vst1.32         {d28[0]}, [r5]
+  .endif
+.endif
+    pop             {r4-r6, lr}
+    bx              lr
+endfunc
+.endm
+
+SAD_X_16xN_LOOP 3 8
+SAD_X_16xN_LOOP 3 16
+SAD_X_16xN_LOOP 3 32
+SAD_X_16xN_LOOP 3 64
+
+SAD_X_16xN_LOOP 4 8
+SAD_X_16xN_LOOP 4 16
+SAD_X_16xN_LOOP 4 32
+SAD_X_16xN_LOOP 4 64
+
+.macro SAD_X_32 x
+    vld1.8          {q0}, [r0]!
+    vld1.8          {q1}, [r1]!
+    vld1.8          {q2}, [r2]!
+    vld1.8          {q3}, [r3]!
+    vabal.u8        q8, d0, d2
+    vabal.u8        q9, d1, d3
+    vabal.u8        q10, d0, d4
+    vabal.u8        q11, d1, d5
+    vabal.u8        q12, d0, d6
+    vabal.u8        q13, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr]!
+    vabal.u8        q14, d0, d6
+    vabal.u8        q15, d1, d7
+.endif
+    vld1.8          {q0}, [r0], r12
+    vld1.8          {q1}, [r1], r4
+    vld1.8          {q2}, [r2], r4
+    vld1.8          {q3}, [r3], r4
+    vabal.u8        q8, d0, d2
+    vabal.u8        q9, d1, d3
+    vabal.u8        q10, d0, d4
+    vabal.u8        q11, d1, d5
+    vabal.u8        q12, d0, d6
+    vabal.u8        q13, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr], r4
+    vabal.u8        q14, d0, d6
+    vabal.u8        q15, d1, d7
+.endif
+.endm
+
+.macro SAD_X_32xN x, h
+function x265_sad_x\x\()_32x\h\()_neon
+    push            {r4-r6, lr}
+.if \x == 3
+    ldrd            r4, r5, [sp, #16]
+.else
+    ldr             lr, [sp, #16]
+    ldrd            r4, r5, [sp, #20]
+.endif
+    mov             r12, #FENC_STRIDE
+    sub             r12, #16
+    sub             r4, #16
+    mov             r6, #\h/8
+    veor.u8         q8, q8
+    veor.u8         q9, q9
+    veor.u8         q10, q10
+    veor.u8         q11, q11
+    veor.u8         q12, q12
+    veor.u8         q13, q13
+.if \x == 4
+    veor.u8         q14, q14
+    veor.u8         q15, q15
+.endif
+
+loop_sad_x\x\()_32x\h:
+.rept 8
+    SAD_X_32 \x
+.endr
+    subs            r6, #1
+    bgt             loop_sad_x\x\()_32x\h
+
+.if \h <= 32
+    vadd.u16        q8, q8, q9
+    vadd.u16        q10, q10, q11
+    vadd.u16        q12, q12, q13
+  .if \x == 4
+    vadd.u16        q14, q14, q15
+  .endif
+    vadd.u16        d16, d16, d17
+    vadd.u16        d20, d20, d21
+    vadd.u16        d24, d24, d25
+  .if \x == 4
+    vadd.u16        d28, d28, d29
+  .endif
+.else
+    vpaddl.u16      q8, q8
+    vpaddl.u16      q9, q9
+    vpaddl.u16      q10, q10
+    vpaddl.u16      q11, q11
+    vpaddl.u16      q12, q12
+    vpaddl.u16      q13, q13
+  .if \x == 4
+    vpaddl.u16      q14, q14
+    vpaddl.u16      q15, q15
+  .endif
+    vadd.u32        q8, q8, q9
+    vadd.u32        q10, q10, q11
+    vadd.u32        q12, q12, q13
+  .if \x == 4
+    vadd.u32        q14, q14, q15
+  .endif
+    vadd.u32        d16, d16, d17
+    vadd.u32        d20, d20, d21
+    vadd.u32        d24, d24, d25
+  .if \x == 4
+    vadd.u32        d28, d28, d29
+  .endif
+.endif
+
+.if \h <= 16
+    vpadd.u16       d0, d16, d20
+    vpadd.u16       d1, d24, d28
+    vpaddl.u16      q0, q0
+  .if \x == 3
+    vst1.32         {d0}, [r5]!
+    vst1.32         {d1[0]}, [r5, :32]
+  .else
+    vst1.32         {d0-d1}, [r5]
+  .endif
+.elseif \h <= 32
+    vpaddl.u16      d16, d16
+    vpaddl.u16      d20, d20
+    vpaddl.u16      d24, d24
+  .if \x == 4
+    vpaddl.u16      d28, d28
+  .endif
+    vpaddl.u32      d16, d16
+    vpaddl.u32      d20, d20
+    vpaddl.u32      d24, d24
+  .if \x == 4
+    vpaddl.u32      d28, d28
+  .endif
+    vst1.32         {d16[0]}, [r5]!
+    vst1.32         {d20[0]}, [r5]!
+  .if \x == 3
+    vst1.32         {d24[0]}, [r5]
+  .endif
+  .if \x == 4
+    vst1.32         {d24[0]}, [r5]!
+    vst1.32         {d28[0]}, [r5]
+  .endif
+.elseif \h <= 64
+    vpaddl.u32      d16, d16
+    vpaddl.u32      d20, d20
+    vpaddl.u32      d24, d24
+  .if \x == 4
+    vpaddl.u32      d28, d28
+  .endif
+    vst1.32         {d16[0]}, [r5]!
+    vst1.32         {d20[0]}, [r5]!
+  .if \x == 3
+    vst1.32         {d24[0]}, [r5]
+  .endif
+  .if \x == 4
+    vst1.32         {d24[0]}, [r5]!
+    vst1.32         {d28[0]}, [r5]
+  .endif
+.endif
+    pop             {r4-r6, lr}
+    bx              lr
+endfunc
+.endm
+
+SAD_X_32xN 3 8
+SAD_X_32xN 3 16
+SAD_X_32xN 3 24
+SAD_X_32xN 3 32
+SAD_X_32xN 3 64
+
+SAD_X_32xN 4 8
+SAD_X_32xN 4 16
+SAD_X_32xN 4 24
+SAD_X_32xN 4 32
+SAD_X_32xN 4 64
+
+.macro SAD_X_64 x
+.rept 3
+    vld1.8          {q0}, [r0]!
+    vld1.8          {q1}, [r1]!
+    vld1.8          {q2}, [r2]!
+    vld1.8          {q3}, [r3]!
+    vabal.u8        q8, d0, d2
+    vabal.u8        q9, d1, d3
+    vabal.u8        q10, d0, d4
+    vabal.u8        q11, d1, d5
+    vabal.u8        q12, d0, d6
+    vabal.u8        q13, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr]!
+    vabal.u8        q14, d0, d6
+    vabal.u8        q15, d1, d7
+.endif
+.endr
+    vld1.8          {q0}, [r0], r12
+    vld1.8          {q1}, [r1], r4
+    vld1.8          {q2}, [r2], r4
+    vld1.8          {q3}, [r3], r4
+    vabal.u8        q8, d0, d2
+    vabal.u8        q9, d1, d3
+    vabal.u8        q10, d0, d4
+    vabal.u8        q11, d1, d5
+    vabal.u8        q12, d0, d6
+    vabal.u8        q13, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr], r4
+    vabal.u8        q14, d0, d6
+    vabal.u8        q15, d1, d7
+.endif
+.endm
+
+.macro SAD_X_64xN x, h
+function x265_sad_x\x\()_64x\h\()_neon
+    push            {r4-r6, lr}
+.if \x == 3
+    ldrd            r4, r5, [sp, #16]
+.else
+    ldr             lr, [sp, #16]
+    ldrd            r4, r5, [sp, #20]
+.endif
+    mov             r12, #FENC_STRIDE
+    sub             r12, #48
+    sub             r4, #48
+    mov             r6, #\h/8
+    veor.u8         q8, q8
+    veor.u8         q9, q9
+    veor.u8         q10, q10
+    veor.u8         q11, q11
+    veor.u8         q12, q12
+    veor.u8         q13, q13
+.if \x == 4
+    veor.u8         q14, q14
+    veor.u8         q15, q15
+.endif
+.loop_sad_x\x\()_64x\h:
+.rept 8
+    SAD_X_64 \x
+.endr
+    subs            r6, #1
+    bne             .loop_sad_x\x\()_64x\h
+
+.if \h <= 16
+    vadd.u16        q8, q8, q9
+    vadd.u16        q10, q10, q11
+    vadd.u16        q12, q12, q13
+  .if \x == 4
+    vadd.u16        q14, q14, q15
+  .endif
+    vadd.u16        d16, d16, d17
+    vadd.u16        d20, d20, d21
+    vadd.u16        d24, d24, d25
+  .if \x == 4
+    vadd.u16        d28, d28, d29
+  .endif
+.else
+    vpaddl.u16      q8, q8
+    vpaddl.u16      q9, q9
+    vpaddl.u16      q10, q10
+    vpaddl.u16      q11, q11
+    vpaddl.u16      q12, q12
+    vpaddl.u16      q13, q13
+  .if \x == 4
+    vpaddl.u16      q14, q14
+    vpaddl.u16      q15, q15
+  .endif
+    vadd.u32        q8, q8, q9
+    vadd.u32        q10, q10, q11
+    vadd.u32        q12, q12, q13
+  .if \x == 4
+    vadd.u32        q14, q14, q15
+  .endif
+    vadd.u32        d16, d16, d17
+    vadd.u32        d20, d20, d21
+    vadd.u32        d24, d24, d25
+  .if \x == 4
+    vadd.u32        d28, d28, d29
+  .endif
+.endif
+
+.if \h <= 16
+    vpaddl.u16      d16, d16
+    vpaddl.u16      d20, d20
+    vpaddl.u16      d24, d24
+  .if \x == 4
+    vpaddl.u16      d28, d28
+  .endif 
+.endif
+    vpaddl.u32      d16, d16
+    vpaddl.u32      d20, d20
+    vpaddl.u32      d24, d24
+.if \x == 4
+    vpaddl.u32      d28, d28
+.endif
+    vst1.32         {d16[0]}, [r5]!
+    vst1.32         {d20[0]}, [r5]!
+.if \x == 3
+    vst1.32         {d24[0]}, [r5]
+.endif
+.if \x == 4
+    vst1.32         {d24[0]}, [r5]!
+    vst1.32         {d28[0]}, [r5]
+.endif
+    pop             {r4-r6, lr}
+    bx              lr
+endfunc
+.endm
+
+SAD_X_64xN 3 16
+SAD_X_64xN 3 32
+SAD_X_64xN 3 48
+SAD_X_64xN 3 64
+
+SAD_X_64xN 4 16
+SAD_X_64xN 4 32
+SAD_X_64xN 4 48
+SAD_X_64xN 4 64
+
+.macro SAD_X_48 x
+.rept 2
+    vld1.8          {q0}, [r0]!
+    vld1.8          {q1}, [r1]!
+    vld1.8          {q2}, [r2]!
+    vld1.8          {q3}, [r3]!
+    vabal.u8        q8, d0, d2
+    vabal.u8        q9, d1, d3
+    vabal.u8        q10, d0, d4
+    vabal.u8        q11, d1, d5
+    vabal.u8        q12, d0, d6
+    vabal.u8        q13, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr]!
+    vabal.u8        q14, d0, d6
+    vabal.u8        q15, d1, d7
+.endif
+.endr
+    vld1.8          {q0}, [r0], r12
+    vld1.8          {q1}, [r1], r4
+    vld1.8          {q2}, [r2], r4
+    vld1.8          {q3}, [r3], r4
+    vabal.u8        q8, d0, d2
+    vabal.u8        q9, d1, d3
+    vabal.u8        q10, d0, d4
+    vabal.u8        q11, d1, d5
+    vabal.u8        q12, d0, d6
+    vabal.u8        q13, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr], r4
+    vabal.u8        q14, d0, d6
+    vabal.u8        q15, d1, d7
+.endif
+.endm
+
+.macro SAD_X_48x64 x
+function x265_sad_x\x\()_48x64_neon
+    push            {r4-r6, lr}
+.if \x == 3
+    ldrd            r4, r5, [sp, #16]
+.else
+    ldr             lr, [sp, #16]
+    ldrd            r4, r5, [sp, #20]
+.endif
+    mov             r12, #FENC_STRIDE
+    sub             r12, #32
+    sub             r4, #32
+    mov             r6, #8
+    veor.u8         q8, q8
+    veor.u8         q9, q9
+    veor.u8         q10, q10
+    veor.u8         q11, q11
+    veor.u8         q12, q12
+    veor.u8         q13, q13
+.if \x == 4
+    veor.u8         q14, q14
+    veor.u8         q15, q15
+.endif
+
+.loop_sad_x\x\()_48x64:
+.rept 8
+    SAD_X_48 \x
+.endr
+    subs            r6, #1
+    bne             .loop_sad_x\x\()_48x64
+
+    vpaddl.u16      q8, q8
+    vpaddl.u16      q9, q9
+    vpaddl.u16      q10, q10
+    vpaddl.u16      q11, q11
+    vpaddl.u16      q12, q12
+    vpaddl.u16      q13, q13
+.if \x == 4
+    vpaddl.u16      q14, q14
+    vpaddl.u16      q15, q15
+.endif
+    vadd.u32        q8, q8, q9
+    vadd.u32        q10, q10, q11
+    vadd.u32        q12, q12, q13
+.if \x == 4
+    vadd.u32        q14, q14, q15
+.endif
+    vadd.u32        d16, d16, d17
+    vadd.u32        d20, d20, d21
+    vadd.u32        d24, d24, d25
+.if \x == 4
+    vadd.u32        d28, d28, d29
+.endif
+    vpaddl.u32      d16, d16
+    vpaddl.u32      d20, d20
+    vpaddl.u32      d24, d24
+    vpaddl.u32      d28, d28
+.if \x == 4
+    vpaddl.u32      d28, d28
+.endif
+    vst1.32         {d16[0]}, [r5]!
+    vst1.32         {d20[0]}, [r5]!
+.if \x == 3
+    vst1.32         {d24[0]}, [r5]
+.endif
+.if \x == 4
+    vst1.32         {d24[0]}, [r5]!
+    vst1.32         {d28[0]}, [r5]
+.endif
+    pop             {r4-r6, lr}
+    bx              lr
+endfunc
+.endm
+
+SAD_X_48x64 3
+SAD_X_48x64 4
+
+.macro SAD_X_24 x
+    vld1.8          {q0}, [r0]!
+    vld1.8          {q1}, [r1]!
+    vld1.8          {q2}, [r2]!
+    vld1.8          {q3}, [r3]!
+    vabal.u8        q8, d0, d2
+    vabal.u8        q9, d1, d3
+    vabal.u8        q10, d0, d4
+    vabal.u8        q11, d1, d5
+    vabal.u8        q12, d0, d6
+    vabal.u8        q13, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr]!
+    vabal.u8        q14, d0, d6
+    vabal.u8        q15, d1, d7
+.endif
+    vld1.8          {d0}, [r0], r12
+    vld1.8          {d1}, [r1], r4
+    vld1.8          {d2}, [r2], r4
+    vld1.8          {d3}, [r3], r4
+.if \x == 4
+    vld1.8          {d8}, [lr], r4
+.endif
+    vabal.u8        q8, d0, d1
+    vabal.u8        q10, d0, d2
+    vabal.u8        q12, d0, d3
+.if \x == 4
+    vabal.u8        q14, d0, d8
+.endif
+.endm
+
+.macro SAD_X_24x32 x
+function x265_sad_x\x\()_24x32_neon
+     push           {r4-r6, lr}
+.if \x == 3
+    ldrd            r4, r5, [sp, #16]
+.else
+    ldr             lr, [sp, #16]
+    ldrd            r4, r5, [sp, #20]
+.endif
+    mov             r12, #FENC_STRIDE
+    sub             r12, #16
+    sub             r4, #16
+    mov             r6, #4
+    veor.u8         q8, q8
+    veor.u8         q9, q9
+    veor.u8         q10, q10
+    veor.u8         q11, q11
+    veor.u8         q12, q12
+    veor.u8         q13, q13
+.if \x == 4
+    veor.u8         q14, q14
+    veor.u8         q15, q15
+.endif
+
+.loop_sad_x\x\()_24x32:
+.rept 8
+    SAD_X_24 \x
+.endr
+    subs            r6, #1
+    bne             .loop_sad_x\x\()_24x32
+
+    vadd.u16        q8, q8, q9
+    vadd.u16        q10, q10, q11
+    vadd.u16        q12, q12, q13
+.if \x == 4
+    vadd.u16        q14, q14, q15
+.endif
+    vadd.u16        d16, d16, d17
+    vadd.u16        d20, d20, d21
+    vadd.u16        d24, d24, d25
+.if \x == 4
+    vadd.u16        d28, d28, d29
+.endif
+    vpaddl.u16      d16, d16
+    vpaddl.u16      d20, d20
+    vpaddl.u16      d24, d24
+.if \x == 4
+    vpaddl.u16      d28, d28
+.endif
+    vpaddl.u32      d16, d16
+    vpaddl.u32      d20, d20
+    vpaddl.u32      d24, d24
+.if \x == 4
+    vpaddl.u32      d28, d28
+.endif
+.if \x == 4
+    vpaddl.u32      d28, d28
+.endif
+    vst1.32         {d16[0]}, [r5]!
+    vst1.32         {d20[0]}, [r5]!
+.if \x == 3
+    vst1.32         {d24[0]}, [r5]
+.endif
+.if \x == 4
+    vst1.32         {d24[0]}, [r5]!
+    vst1.32         {d28[0]}, [r5]
+.endif
+    pop             {r4-r6, lr}
+    bx              lr
+endfunc
+.endm
+
+SAD_X_24x32 3
+SAD_X_24x32 4
+
+// SAD_X3 and SAD_X4 code end
+
+.macro SAD_X_START_12 x
+    vld1.8          {q0}, [r0], r12
+    vld1.8          {q1}, [r1], r4
+    vld1.8          {q2}, [r2], r4
+    vld1.8          {q3}, [r3], r4
+    vand.u8         q0, q15
+    vand.u8         q1, q15
+    vand.u8         q2, q15
+    vand.u8         q3, q15
+    vabdl.u8        q5, d0, d2
+    vabdl.u8        q8, d1, d3
+    vabdl.u8        q9, d0, d4
+    vabdl.u8        q10, d1, d5
+    vabdl.u8        q11, d0, d6
+    vabdl.u8        q12, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr], r4
+    vand.u8         q3, q15
+    vabdl.u8        q13, d0, d6
+    vabdl.u8        q14, d1, d7
+.endif
+.endm
+
+.macro SAD_X_12 x
+    vld1.8          {q0}, [r0], r12
+    vld1.8          {q1}, [r1], r4
+    vld1.8          {q2}, [r2], r4
+    vld1.8          {q3}, [r3], r4
+    vand.u8         q0, q15
+    vand.u8         q1, q15
+    vand.u8         q2, q15
+    vand.u8         q3, q15
+    vabal.u8        q5, d0, d2
+    vabal.u8        q8, d1, d3
+    vabal.u8        q9, d0, d4
+    vabal.u8        q10, d1, d5
+    vabal.u8        q11, d0, d6
+    vabal.u8        q12, d1, d7
+.if \x == 4
+    vld1.8          {q3}, [lr], r4
+    vand.u8         q3, q15
+    vabal.u8        q13, d0, d6
+    vabal.u8        q14, d1, d7
+.endif
+.endm
+
+.macro SAD_X_12x16 x
+function x265_sad_x\x\()_12x16_neon
+    push            {r4-r5, lr}
+    vpush           {q5}
+.if \x == 3
+    ldrd            r4, r5, [sp, #28]
+.else
+    ldr             lr, [sp, #28]
+    ldrd            r4, r5, [sp, #32]
+.endif
+    movrel          r12, sad12_mask
+    vld1.8          {q15}, [r12]
+    mov             r12, #FENC_STRIDE
+
+    SAD_X_START_12 \x    
+.rept 15
+    SAD_X_12 \x
+.endr
+    vadd.u16        q5, q5, q8
+    vadd.u16        q9, q9, q10
+    vadd.u16        q11, q11, q12
+.if \x == 4
+    vadd.u16        q13, q13, q14
+.endif
+    vadd.u16        d10, d10, d11
+    vadd.u16        d18, d18, d19
+    vadd.u16        d22, d22, d23
+.if \x == 4
+    vadd.u16        d26, d26, d27
+.endif
+    vpadd.u16       d0, d10, d18
+    vpadd.u16       d1, d22, d26
+    vpaddl.u16      q0, q0
+.if \x == 3
+    vst1.32         {d0}, [r5]!
+    vst1.32         {d1[0]}, [r5, :32]
+.else
+    vst1.32         {d0-d1}, [r5]
+.endif
+    vpop            {q5}
+    pop             {r4-r5, lr}
+    bx              lr
+endfunc
+.endm
+
+SAD_X_12x16 3
+SAD_X_12x16 4



More information about the x265-devel mailing list