Ignore:
Timestamp:
Jul 28, 2017 2:51:44 AM (7 years ago)
Author:
nanang
Message:

Re #2004: Update libyuv version from libyuv git master repo dated 27 July 2017, the compile errors on old gcc versions issue persists though.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/third_party/yuv/source/scale_neon.cc

    r5358 r5633  
    2424 
    2525// Read 32x1 throw away even pixels, and write 16x1. 
    26 void ScaleRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, 
    27                         uint8* dst, int dst_width) { 
    28   asm volatile ( 
    29   "1:                                          \n" 
    30     // load even pixels into q0, odd into q1 
    31     MEMACCESS(0) 
    32     "vld2.8     {q0, q1}, [%0]!                \n" 
    33     "subs       %2, %2, #16                    \n"  // 16 processed per loop 
    34     MEMACCESS(1) 
    35     "vst1.8     {q1}, [%1]!                    \n"  // store odd pixels 
    36     "bgt        1b                             \n" 
    37   : "+r"(src_ptr),          // %0 
    38     "+r"(dst),              // %1 
    39     "+r"(dst_width)         // %2 
    40   : 
    41   : "q0", "q1"              // Clobber List 
    42   ); 
     26void ScaleRowDown2_NEON(const uint8* src_ptr, 
     27                        ptrdiff_t src_stride, 
     28                        uint8* dst, 
     29                        int dst_width) { 
     30  (void)src_stride; 
     31  asm volatile( 
     32      "1:                                          \n" 
     33      // load even pixels into q0, odd into q1 
     34      "vld2.8     {q0, q1}, [%0]!                \n" 
     35      "subs       %2, %2, #16                    \n"  // 16 processed per loop 
     36      "vst1.8     {q1}, [%1]!                    \n"  // store odd pixels 
     37      "bgt        1b                             \n" 
     38      : "+r"(src_ptr),   // %0 
     39        "+r"(dst),       // %1 
     40        "+r"(dst_width)  // %2 
     41      : 
     42      : "q0", "q1"  // Clobber List 
     43      ); 
    4344} 
    4445 
    4546// Read 32x1 average down and write 16x1. 
    46 void ScaleRowDown2Linear_NEON(const uint8* src_ptr, ptrdiff_t src_stride, 
    47                            uint8* dst, int dst_width) { 
    48   asm volatile ( 
    49   "1:                                          \n" 
    50     MEMACCESS(0) 
    51     "vld1.8     {q0, q1}, [%0]!                \n"  // load pixels and post inc 
    52     "subs       %2, %2, #16                    \n"  // 16 processed per loop 
    53     "vpaddl.u8  q0, q0                         \n"  // add adjacent 
    54     "vpaddl.u8  q1, q1                         \n" 
    55     "vrshrn.u16 d0, q0, #1                     \n"  // downshift, round and pack 
    56     "vrshrn.u16 d1, q1, #1                     \n" 
    57     MEMACCESS(1) 
    58     "vst1.8     {q0}, [%1]!                    \n" 
    59     "bgt        1b                             \n" 
    60   : "+r"(src_ptr),          // %0 
    61     "+r"(dst),              // %1 
    62     "+r"(dst_width)         // %2 
    63   : 
    64   : "q0", "q1"     // Clobber List 
    65   ); 
     47void ScaleRowDown2Linear_NEON(const uint8* src_ptr, 
     48                              ptrdiff_t src_stride, 
     49                              uint8* dst, 
     50                              int dst_width) { 
     51  (void)src_stride; 
     52  asm volatile( 
     53      "1:                                          \n" 
     54      "vld1.8     {q0, q1}, [%0]!                \n"  // load pixels and post 
     55                                                      // inc 
     56      "subs       %2, %2, #16                    \n"  // 16 processed per loop 
     57      "vpaddl.u8  q0, q0                         \n"  // add adjacent 
     58      "vpaddl.u8  q1, q1                         \n" 
     59      "vrshrn.u16 d0, q0, #1                     \n"  // downshift, round and 
     60                                                      // pack 
     61      "vrshrn.u16 d1, q1, #1                     \n" 
     62      "vst1.8     {q0}, [%1]!                    \n" 
     63      "bgt        1b                             \n" 
     64      : "+r"(src_ptr),   // %0 
     65        "+r"(dst),       // %1 
     66        "+r"(dst_width)  // %2 
     67      : 
     68      : "q0", "q1"  // Clobber List 
     69      ); 
    6670} 
    6771 
    6872// Read 32x2 average down and write 16x1. 
    69 void ScaleRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, 
    70                            uint8* dst, int dst_width) { 
    71   asm volatile ( 
    72     // change the stride to row 2 pointer 
    73     "add        %1, %0                         \n" 
    74   "1:                                          \n" 
    75     MEMACCESS(0) 
    76     "vld1.8     {q0, q1}, [%0]!                \n"  // load row 1 and post inc 
    77     MEMACCESS(1) 
    78     "vld1.8     {q2, q3}, [%1]!                \n"  // load row 2 and post inc 
    79     "subs       %3, %3, #16                    \n"  // 16 processed per loop 
    80     "vpaddl.u8  q0, q0                         \n"  // row 1 add adjacent 
    81     "vpaddl.u8  q1, q1                         \n" 
    82     "vpadal.u8  q0, q2                         \n"  // row 2 add adjacent + row1 
    83     "vpadal.u8  q1, q3                         \n" 
    84     "vrshrn.u16 d0, q0, #2                     \n"  // downshift, round and pack 
    85     "vrshrn.u16 d1, q1, #2                     \n" 
    86     MEMACCESS(2) 
    87     "vst1.8     {q0}, [%2]!                    \n" 
    88     "bgt        1b                             \n" 
    89   : "+r"(src_ptr),          // %0 
    90     "+r"(src_stride),       // %1 
    91     "+r"(dst),              // %2 
    92     "+r"(dst_width)         // %3 
    93   : 
    94   : "q0", "q1", "q2", "q3"     // Clobber List 
    95   ); 
    96 } 
    97  
    98 void ScaleRowDown4_NEON(const uint8* src_ptr, ptrdiff_t src_stride, 
    99                         uint8* dst_ptr, int dst_width) { 
    100   asm volatile ( 
    101   "1:                                          \n" 
    102     MEMACCESS(0) 
    103     "vld4.8     {d0, d1, d2, d3}, [%0]!        \n" // src line 0 
    104     "subs       %2, %2, #8                     \n" // 8 processed per loop 
    105     MEMACCESS(1) 
    106     "vst1.8     {d2}, [%1]!                    \n" 
    107     "bgt        1b                             \n" 
    108   : "+r"(src_ptr),          // %0 
    109     "+r"(dst_ptr),          // %1 
    110     "+r"(dst_width)         // %2 
    111   : 
    112   : "q0", "q1", "memory", "cc" 
    113   ); 
    114 } 
    115  
    116 void ScaleRowDown4Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, 
    117                            uint8* dst_ptr, int dst_width) { 
     73void ScaleRowDown2Box_NEON(const uint8* src_ptr, 
     74                           ptrdiff_t src_stride, 
     75                           uint8* dst, 
     76                           int dst_width) { 
     77  asm volatile( 
     78      // change the stride to row 2 pointer 
     79      "add        %1, %0                         \n" 
     80      "1:                                          \n" 
     81      "vld1.8     {q0, q1}, [%0]!                \n"  // load row 1 and post inc 
     82      "vld1.8     {q2, q3}, [%1]!                \n"  // load row 2 and post inc 
     83      "subs       %3, %3, #16                    \n"  // 16 processed per loop 
     84      "vpaddl.u8  q0, q0                         \n"  // row 1 add adjacent 
     85      "vpaddl.u8  q1, q1                         \n" 
     86      "vpadal.u8  q0, q2                         \n"  // row 2 add adjacent + 
     87                                                      // row1 
     88      "vpadal.u8  q1, q3                         \n" 
     89      "vrshrn.u16 d0, q0, #2                     \n"  // downshift, round and 
     90                                                      // pack 
     91      "vrshrn.u16 d1, q1, #2                     \n" 
     92      "vst1.8     {q0}, [%2]!                    \n" 
     93      "bgt        1b                             \n" 
     94      : "+r"(src_ptr),     // %0 
     95        "+r"(src_stride),  // %1 
     96        "+r"(dst),         // %2 
     97        "+r"(dst_width)    // %3 
     98      : 
     99      : "q0", "q1", "q2", "q3"  // Clobber List 
     100      ); 
     101} 
     102 
     103void ScaleRowDown4_NEON(const uint8* src_ptr, 
     104                        ptrdiff_t src_stride, 
     105                        uint8* dst_ptr, 
     106                        int dst_width) { 
     107  (void)src_stride; 
     108  asm volatile( 
     109      "1:                                          \n" 
     110      "vld4.8     {d0, d1, d2, d3}, [%0]!        \n"  // src line 0 
     111      "subs       %2, %2, #8                     \n"  // 8 processed per loop 
     112      "vst1.8     {d2}, [%1]!                    \n" 
     113      "bgt        1b                             \n" 
     114      : "+r"(src_ptr),   // %0 
     115        "+r"(dst_ptr),   // %1 
     116        "+r"(dst_width)  // %2 
     117      : 
     118      : "q0", "q1", "memory", "cc"); 
     119} 
     120 
     121void ScaleRowDown4Box_NEON(const uint8* src_ptr, 
     122                           ptrdiff_t src_stride, 
     123                           uint8* dst_ptr, 
     124                           int dst_width) { 
    118125  const uint8* src_ptr1 = src_ptr + src_stride; 
    119126  const uint8* src_ptr2 = src_ptr + src_stride * 2; 
    120127  const uint8* src_ptr3 = src_ptr + src_stride * 3; 
    121 asm volatile ( 
    122   "1:                                          \n" 
    123     MEMACCESS(0) 
    124     "vld1.8     {q0}, [%0]!                    \n"   // load up 16x4 
    125     MEMACCESS(3) 
    126     "vld1.8     {q1}, [%3]!                    \n" 
    127     MEMACCESS(4) 
    128     "vld1.8     {q2}, [%4]!                    \n" 
    129     MEMACCESS(5) 
    130     "vld1.8     {q3}, [%5]!                    \n" 
    131     "subs       %2, %2, #4                     \n" 
    132     "vpaddl.u8  q0, q0                         \n" 
    133     "vpadal.u8  q0, q1                         \n" 
    134     "vpadal.u8  q0, q2                         \n" 
    135     "vpadal.u8  q0, q3                         \n" 
    136     "vpaddl.u16 q0, q0                         \n" 
    137     "vrshrn.u32 d0, q0, #4                     \n"   // divide by 16 w/rounding 
    138     "vmovn.u16  d0, q0                         \n" 
    139     MEMACCESS(1) 
    140     "vst1.32    {d0[0]}, [%1]!                 \n" 
    141     "bgt        1b                             \n" 
    142   : "+r"(src_ptr),   // %0 
    143     "+r"(dst_ptr),   // %1 
    144     "+r"(dst_width), // %2 
    145     "+r"(src_ptr1),  // %3 
    146     "+r"(src_ptr2),  // %4 
    147     "+r"(src_ptr3)   // %5 
    148   : 
    149   : "q0", "q1", "q2", "q3", "memory", "cc" 
    150   ); 
     128  asm volatile( 
     129      "1:                                          \n" 
     130      "vld1.8     {q0}, [%0]!                    \n"  // load up 16x4 
     131      "vld1.8     {q1}, [%3]!                    \n" 
     132      "vld1.8     {q2}, [%4]!                    \n" 
     133      "vld1.8     {q3}, [%5]!                    \n" 
     134      "subs       %2, %2, #4                     \n" 
     135      "vpaddl.u8  q0, q0                         \n" 
     136      "vpadal.u8  q0, q1                         \n" 
     137      "vpadal.u8  q0, q2                         \n" 
     138      "vpadal.u8  q0, q3                         \n" 
     139      "vpaddl.u16 q0, q0                         \n" 
     140      "vrshrn.u32 d0, q0, #4                     \n"  // divide by 16 w/rounding 
     141      "vmovn.u16  d0, q0                         \n" 
     142      "vst1.32    {d0[0]}, [%1]!                 \n" 
     143      "bgt        1b                             \n" 
     144      : "+r"(src_ptr),    // %0 
     145        "+r"(dst_ptr),    // %1 
     146        "+r"(dst_width),  // %2 
     147        "+r"(src_ptr1),   // %3 
     148        "+r"(src_ptr2),   // %4 
     149        "+r"(src_ptr3)    // %5 
     150      : 
     151      : "q0", "q1", "q2", "q3", "memory", "cc"); 
    151152} 
    152153 
     
    156157void ScaleRowDown34_NEON(const uint8* src_ptr, 
    157158                         ptrdiff_t src_stride, 
    158                          uint8* dst_ptr, int dst_width) { 
    159   asm volatile ( 
    160   "1:                                          \n" 
    161     MEMACCESS(0) 
    162     "vld4.8     {d0, d1, d2, d3}, [%0]!      \n" // src line 0 
    163     "subs       %2, %2, #24                  \n" 
    164     "vmov       d2, d3                       \n" // order d0, d1, d2 
    165     MEMACCESS(1) 
    166     "vst3.8     {d0, d1, d2}, [%1]!          \n" 
    167     "bgt        1b                           \n" 
    168   : "+r"(src_ptr),          // %0 
    169     "+r"(dst_ptr),          // %1 
    170     "+r"(dst_width)         // %2 
    171   : 
    172   : "d0", "d1", "d2", "d3", "memory", "cc" 
    173   ); 
     159                         uint8* dst_ptr, 
     160                         int dst_width) { 
     161  (void)src_stride; 
     162  asm volatile( 
     163      "1:                                          \n" 
     164      "vld4.8     {d0, d1, d2, d3}, [%0]!      \n"  // src line 0 
     165      "subs       %2, %2, #24                  \n" 
     166      "vmov       d2, d3                       \n"  // order d0, d1, d2 
     167      "vst3.8     {d0, d1, d2}, [%1]!          \n" 
     168      "bgt        1b                           \n" 
     169      : "+r"(src_ptr),   // %0 
     170        "+r"(dst_ptr),   // %1 
     171        "+r"(dst_width)  // %2 
     172      : 
     173      : "d0", "d1", "d2", "d3", "memory", "cc"); 
    174174} 
    175175 
    176176void ScaleRowDown34_0_Box_NEON(const uint8* src_ptr, 
    177177                               ptrdiff_t src_stride, 
    178                                uint8* dst_ptr, int dst_width) { 
    179   asm volatile ( 
    180     "vmov.u8    d24, #3                        \n" 
    181     "add        %3, %0                         \n" 
    182   "1:                                          \n" 
    183     MEMACCESS(0) 
    184     "vld4.8       {d0, d1, d2, d3}, [%0]!      \n" // src line 0 
    185     MEMACCESS(3) 
    186     "vld4.8       {d4, d5, d6, d7}, [%3]!      \n" // src line 1 
    187     "subs         %2, %2, #24                  \n" 
    188  
    189     // filter src line 0 with src line 1 
    190     // expand chars to shorts to allow for room 
    191     // when adding lines together 
    192     "vmovl.u8     q8, d4                       \n" 
    193     "vmovl.u8     q9, d5                       \n" 
    194     "vmovl.u8     q10, d6                      \n" 
    195     "vmovl.u8     q11, d7                      \n" 
    196  
    197     // 3 * line_0 + line_1 
    198     "vmlal.u8     q8, d0, d24                  \n" 
    199     "vmlal.u8     q9, d1, d24                  \n" 
    200     "vmlal.u8     q10, d2, d24                 \n" 
    201     "vmlal.u8     q11, d3, d24                 \n" 
    202  
    203     // (3 * line_0 + line_1) >> 2 
    204     "vqrshrn.u16  d0, q8, #2                   \n" 
    205     "vqrshrn.u16  d1, q9, #2                   \n" 
    206     "vqrshrn.u16  d2, q10, #2                  \n" 
    207     "vqrshrn.u16  d3, q11, #2                  \n" 
    208  
    209     // a0 = (src[0] * 3 + s[1] * 1) >> 2 
    210     "vmovl.u8     q8, d1                       \n" 
    211     "vmlal.u8     q8, d0, d24                  \n" 
    212     "vqrshrn.u16  d0, q8, #2                   \n" 
    213  
    214     // a1 = (src[1] * 1 + s[2] * 1) >> 1 
    215     "vrhadd.u8    d1, d1, d2                   \n" 
    216  
    217     // a2 = (src[2] * 1 + s[3] * 3) >> 2 
    218     "vmovl.u8     q8, d2                       \n" 
    219     "vmlal.u8     q8, d3, d24                  \n" 
    220     "vqrshrn.u16  d2, q8, #2                   \n" 
    221  
    222     MEMACCESS(1) 
    223     "vst3.8       {d0, d1, d2}, [%1]!          \n" 
    224  
    225     "bgt          1b                           \n" 
    226   : "+r"(src_ptr),          // %0 
    227     "+r"(dst_ptr),          // %1 
    228     "+r"(dst_width),        // %2 
    229     "+r"(src_stride)        // %3 
    230   : 
    231   : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "d24", "memory", "cc" 
    232   ); 
     178                               uint8* dst_ptr, 
     179                               int dst_width) { 
     180  asm volatile( 
     181      "vmov.u8    d24, #3                        \n" 
     182      "add        %3, %0                         \n" 
     183      "1:                                          \n" 
     184      "vld4.8       {d0, d1, d2, d3}, [%0]!      \n"  // src line 0 
     185      "vld4.8       {d4, d5, d6, d7}, [%3]!      \n"  // src line 1 
     186      "subs         %2, %2, #24                  \n" 
     187 
     188      // filter src line 0 with src line 1 
     189      // expand chars to shorts to allow for room 
     190      // when adding lines together 
     191      "vmovl.u8     q8, d4                       \n" 
     192      "vmovl.u8     q9, d5                       \n" 
     193      "vmovl.u8     q10, d6                      \n" 
     194      "vmovl.u8     q11, d7                      \n" 
     195 
     196      // 3 * line_0 + line_1 
     197      "vmlal.u8     q8, d0, d24                  \n" 
     198      "vmlal.u8     q9, d1, d24                  \n" 
     199      "vmlal.u8     q10, d2, d24                 \n" 
     200      "vmlal.u8     q11, d3, d24                 \n" 
     201 
     202      // (3 * line_0 + line_1) >> 2 
     203      "vqrshrn.u16  d0, q8, #2                   \n" 
     204      "vqrshrn.u16  d1, q9, #2                   \n" 
     205      "vqrshrn.u16  d2, q10, #2                  \n" 
     206      "vqrshrn.u16  d3, q11, #2                  \n" 
     207 
     208      // a0 = (src[0] * 3 + s[1] * 1) >> 2 
     209      "vmovl.u8     q8, d1                       \n" 
     210      "vmlal.u8     q8, d0, d24                  \n" 
     211      "vqrshrn.u16  d0, q8, #2                   \n" 
     212 
     213      // a1 = (src[1] * 1 + s[2] * 1) >> 1 
     214      "vrhadd.u8    d1, d1, d2                   \n" 
     215 
     216      // a2 = (src[2] * 1 + s[3] * 3) >> 2 
     217      "vmovl.u8     q8, d2                       \n" 
     218      "vmlal.u8     q8, d3, d24                  \n" 
     219      "vqrshrn.u16  d2, q8, #2                   \n" 
     220 
     221      "vst3.8       {d0, d1, d2}, [%1]!          \n" 
     222 
     223      "bgt          1b                           \n" 
     224      : "+r"(src_ptr),    // %0 
     225        "+r"(dst_ptr),    // %1 
     226        "+r"(dst_width),  // %2 
     227        "+r"(src_stride)  // %3 
     228      : 
     229      : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "d24", "memory", 
     230        "cc"); 
    233231} 
    234232 
    235233void ScaleRowDown34_1_Box_NEON(const uint8* src_ptr, 
    236234                               ptrdiff_t src_stride, 
    237                                uint8* dst_ptr, int dst_width) { 
    238   asm volatile ( 
    239     "vmov.u8    d24, #3                        \n" 
    240     "add        %3, %0                         \n" 
    241   "1:                                          \n" 
    242     MEMACCESS(0) 
    243     "vld4.8       {d0, d1, d2, d3}, [%0]!      \n" // src line 0 
    244     MEMACCESS(3) 
    245     "vld4.8       {d4, d5, d6, d7}, [%3]!      \n" // src line 1 
    246     "subs         %2, %2, #24                  \n" 
    247     // average src line 0 with src line 1 
    248     "vrhadd.u8    q0, q0, q2                   \n" 
    249     "vrhadd.u8    q1, q1, q3                   \n" 
    250  
    251     // a0 = (src[0] * 3 + s[1] * 1) >> 2 
    252     "vmovl.u8     q3, d1                       \n" 
    253     "vmlal.u8     q3, d0, d24                  \n" 
    254     "vqrshrn.u16  d0, q3, #2                   \n" 
    255  
    256     // a1 = (src[1] * 1 + s[2] * 1) >> 1 
    257     "vrhadd.u8    d1, d1, d2                   \n" 
    258  
    259     // a2 = (src[2] * 1 + s[3] * 3) >> 2 
    260     "vmovl.u8     q3, d2                       \n" 
    261     "vmlal.u8     q3, d3, d24                  \n" 
    262     "vqrshrn.u16  d2, q3, #2                   \n" 
    263  
    264     MEMACCESS(1) 
    265     "vst3.8       {d0, d1, d2}, [%1]!          \n" 
    266     "bgt          1b                           \n" 
    267   : "+r"(src_ptr),          // %0 
    268     "+r"(dst_ptr),          // %1 
    269     "+r"(dst_width),        // %2 
    270     "+r"(src_stride)        // %3 
    271   : 
    272   : "r4", "q0", "q1", "q2", "q3", "d24", "memory", "cc" 
    273   ); 
     235                               uint8* dst_ptr, 
     236                               int dst_width) { 
     237  asm volatile( 
     238      "vmov.u8    d24, #3                        \n" 
     239      "add        %3, %0                         \n" 
     240      "1:                                          \n" 
     241      "vld4.8       {d0, d1, d2, d3}, [%0]!      \n"  // src line 0 
     242      "vld4.8       {d4, d5, d6, d7}, [%3]!      \n"  // src line 1 
     243      "subs         %2, %2, #24                  \n" 
     244      // average src line 0 with src line 1 
     245      "vrhadd.u8    q0, q0, q2                   \n" 
     246      "vrhadd.u8    q1, q1, q3                   \n" 
     247 
     248      // a0 = (src[0] * 3 + s[1] * 1) >> 2 
     249      "vmovl.u8     q3, d1                       \n" 
     250      "vmlal.u8     q3, d0, d24                  \n" 
     251      "vqrshrn.u16  d0, q3, #2                   \n" 
     252 
     253      // a1 = (src[1] * 1 + s[2] * 1) >> 1 
     254      "vrhadd.u8    d1, d1, d2                   \n" 
     255 
     256      // a2 = (src[2] * 1 + s[3] * 3) >> 2 
     257      "vmovl.u8     q3, d2                       \n" 
     258      "vmlal.u8     q3, d3, d24                  \n" 
     259      "vqrshrn.u16  d2, q3, #2                   \n" 
     260 
     261      "vst3.8       {d0, d1, d2}, [%1]!          \n" 
     262      "bgt          1b                           \n" 
     263      : "+r"(src_ptr),    // %0 
     264        "+r"(dst_ptr),    // %1 
     265        "+r"(dst_width),  // %2 
     266        "+r"(src_stride)  // %3 
     267      : 
     268      : "r4", "q0", "q1", "q2", "q3", "d24", "memory", "cc"); 
    274269} 
    275270 
    276271#define HAS_SCALEROWDOWN38_NEON 
    277 static uvec8 kShuf38 = 
    278   { 0, 3, 6, 8, 11, 14, 16, 19, 22, 24, 27, 30, 0, 0, 0, 0 }; 
    279 static uvec8 kShuf38_2 = 
    280   { 0, 8, 16, 2, 10, 17, 4, 12, 18, 6, 14, 19, 0, 0, 0, 0 }; 
    281 static vec16 kMult38_Div6 = 
    282   { 65536 / 12, 65536 / 12, 65536 / 12, 65536 / 12, 
    283     65536 / 12, 65536 / 12, 65536 / 12, 65536 / 12 }; 
    284 static vec16 kMult38_Div9 = 
    285   { 65536 / 18, 65536 / 18, 65536 / 18, 65536 / 18, 
    286     65536 / 18, 65536 / 18, 65536 / 18, 65536 / 18 }; 
     272static uvec8 kShuf38 = {0, 3, 6, 8, 11, 14, 16, 19, 22, 24, 27, 30, 0, 0, 0, 0}; 
     273static uvec8 kShuf38_2 = {0,  8, 16, 2,  10, 17, 4, 12, 
     274                          18, 6, 14, 19, 0,  0,  0, 0}; 
     275static vec16 kMult38_Div6 = {65536 / 12, 65536 / 12, 65536 / 12, 65536 / 12, 
     276                             65536 / 12, 65536 / 12, 65536 / 12, 65536 / 12}; 
     277static vec16 kMult38_Div9 = {65536 / 18, 65536 / 18, 65536 / 18, 65536 / 18, 
     278                             65536 / 18, 65536 / 18, 65536 / 18, 65536 / 18}; 
    287279 
    288280// 32 -> 12 
    289281void ScaleRowDown38_NEON(const uint8* src_ptr, 
    290282                         ptrdiff_t src_stride, 
    291                          uint8* dst_ptr, int dst_width) { 
    292   asm volatile ( 
    293     MEMACCESS(3) 
    294     "vld1.8     {q3}, [%3]                     \n" 
    295   "1:                                          \n" 
    296     MEMACCESS(0) 
    297     "vld1.8     {d0, d1, d2, d3}, [%0]!        \n" 
    298     "subs       %2, %2, #12                    \n" 
    299     "vtbl.u8    d4, {d0, d1, d2, d3}, d6       \n" 
    300     "vtbl.u8    d5, {d0, d1, d2, d3}, d7       \n" 
    301     MEMACCESS(1) 
    302     "vst1.8     {d4}, [%1]!                    \n" 
    303     MEMACCESS(1) 
    304     "vst1.32    {d5[0]}, [%1]!                 \n" 
    305     "bgt        1b                             \n" 
    306   : "+r"(src_ptr),          // %0 
    307     "+r"(dst_ptr),          // %1 
    308     "+r"(dst_width)         // %2 
    309   : "r"(&kShuf38)           // %3 
    310   : "d0", "d1", "d2", "d3", "d4", "d5", "memory", "cc" 
    311   ); 
     283                         uint8* dst_ptr, 
     284                         int dst_width) { 
     285  (void)src_stride; 
     286  asm volatile( 
     287      "vld1.8     {q3}, [%3]                     \n" 
     288      "1:                                          \n" 
     289      "vld1.8     {d0, d1, d2, d3}, [%0]!        \n" 
     290      "subs       %2, %2, #12                    \n" 
     291      "vtbl.u8    d4, {d0, d1, d2, d3}, d6       \n" 
     292      "vtbl.u8    d5, {d0, d1, d2, d3}, d7       \n" 
     293      "vst1.8     {d4}, [%1]!                    \n" 
     294      "vst1.32    {d5[0]}, [%1]!                 \n" 
     295      "bgt        1b                             \n" 
     296      : "+r"(src_ptr),   // %0 
     297        "+r"(dst_ptr),   // %1 
     298        "+r"(dst_width)  // %2 
     299      : "r"(&kShuf38)    // %3 
     300      : "d0", "d1", "d2", "d3", "d4", "d5", "memory", "cc"); 
    312301} 
    313302 
     
    315304void OMITFP ScaleRowDown38_3_Box_NEON(const uint8* src_ptr, 
    316305                                      ptrdiff_t src_stride, 
    317                                       uint8* dst_ptr, int dst_width) { 
     306                                      uint8* dst_ptr, 
     307                                      int dst_width) { 
    318308  const uint8* src_ptr1 = src_ptr + src_stride * 2; 
    319309 
    320   asm volatile ( 
    321     MEMACCESS(5) 
    322     "vld1.16    {q13}, [%5]                    \n" 
    323     MEMACCESS(6) 
    324     "vld1.8     {q14}, [%6]                    \n" 
    325     MEMACCESS(7) 
    326     "vld1.8     {q15}, [%7]                    \n" 
    327     "add        %3, %0                         \n" 
    328   "1:                                          \n" 
    329  
    330     // d0 = 00 40 01 41 02 42 03 43 
    331     // d1 = 10 50 11 51 12 52 13 53 
    332     // d2 = 20 60 21 61 22 62 23 63 
    333     // d3 = 30 70 31 71 32 72 33 73 
    334     MEMACCESS(0) 
    335     "vld4.8       {d0, d1, d2, d3}, [%0]!      \n" 
    336     MEMACCESS(3) 
    337     "vld4.8       {d4, d5, d6, d7}, [%3]!      \n" 
    338     MEMACCESS(4) 
    339     "vld4.8       {d16, d17, d18, d19}, [%4]!  \n" 
    340     "subs         %2, %2, #12                  \n" 
    341  
    342     // Shuffle the input data around to get align the data 
    343     //  so adjacent data can be added. 0,1 - 2,3 - 4,5 - 6,7 
    344     // d0 = 00 10 01 11 02 12 03 13 
    345     // d1 = 40 50 41 51 42 52 43 53 
    346     "vtrn.u8      d0, d1                       \n" 
    347     "vtrn.u8      d4, d5                       \n" 
    348     "vtrn.u8      d16, d17                     \n" 
    349  
    350     // d2 = 20 30 21 31 22 32 23 33 
    351     // d3 = 60 70 61 71 62 72 63 73 
    352     "vtrn.u8      d2, d3                       \n" 
    353     "vtrn.u8      d6, d7                       \n" 
    354     "vtrn.u8      d18, d19                     \n" 
    355  
    356     // d0 = 00+10 01+11 02+12 03+13 
    357     // d2 = 40+50 41+51 42+52 43+53 
    358     "vpaddl.u8    q0, q0                       \n" 
    359     "vpaddl.u8    q2, q2                       \n" 
    360     "vpaddl.u8    q8, q8                       \n" 
    361  
    362     // d3 = 60+70 61+71 62+72 63+73 
    363     "vpaddl.u8    d3, d3                       \n" 
    364     "vpaddl.u8    d7, d7                       \n" 
    365     "vpaddl.u8    d19, d19                     \n" 
    366  
    367     // combine source lines 
    368     "vadd.u16     q0, q2                       \n" 
    369     "vadd.u16     q0, q8                       \n" 
    370     "vadd.u16     d4, d3, d7                   \n" 
    371     "vadd.u16     d4, d19                      \n" 
    372  
    373     // dst_ptr[3] = (s[6 + st * 0] + s[7 + st * 0] 
    374     //             + s[6 + st * 1] + s[7 + st * 1] 
    375     //             + s[6 + st * 2] + s[7 + st * 2]) / 6 
    376     "vqrdmulh.s16 q2, q2, q13                  \n" 
    377     "vmovn.u16    d4, q2                       \n" 
    378  
    379     // Shuffle 2,3 reg around so that 2 can be added to the 
    380     //  0,1 reg and 3 can be added to the 4,5 reg. This 
    381     //  requires expanding from u8 to u16 as the 0,1 and 4,5 
    382     //  registers are already expanded. Then do transposes 
    383     //  to get aligned. 
    384     // q2 = xx 20 xx 30 xx 21 xx 31 xx 22 xx 32 xx 23 xx 33 
    385     "vmovl.u8     q1, d2                       \n" 
    386     "vmovl.u8     q3, d6                       \n" 
    387     "vmovl.u8     q9, d18                      \n" 
    388  
    389     // combine source lines 
    390     "vadd.u16     q1, q3                       \n" 
    391     "vadd.u16     q1, q9                       \n" 
    392  
    393     // d4 = xx 20 xx 30 xx 22 xx 32 
    394     // d5 = xx 21 xx 31 xx 23 xx 33 
    395     "vtrn.u32     d2, d3                       \n" 
    396  
    397     // d4 = xx 20 xx 21 xx 22 xx 23 
    398     // d5 = xx 30 xx 31 xx 32 xx 33 
    399     "vtrn.u16     d2, d3                       \n" 
    400  
    401     // 0+1+2, 3+4+5 
    402     "vadd.u16     q0, q1                       \n" 
    403  
    404     // Need to divide, but can't downshift as the the value 
    405     //  isn't a power of 2. So multiply by 65536 / n 
    406     //  and take the upper 16 bits. 
    407     "vqrdmulh.s16 q0, q0, q15                  \n" 
    408  
    409     // Align for table lookup, vtbl requires registers to 
    410     //  be adjacent 
    411     "vmov.u8      d2, d4                       \n" 
    412  
    413     "vtbl.u8      d3, {d0, d1, d2}, d28        \n" 
    414     "vtbl.u8      d4, {d0, d1, d2}, d29        \n" 
    415  
    416     MEMACCESS(1) 
    417     "vst1.8       {d3}, [%1]!                  \n" 
    418     MEMACCESS(1) 
    419     "vst1.32      {d4[0]}, [%1]!               \n" 
    420     "bgt          1b                           \n" 
    421   : "+r"(src_ptr),          // %0 
    422     "+r"(dst_ptr),          // %1 
    423     "+r"(dst_width),        // %2 
    424     "+r"(src_stride),       // %3 
    425     "+r"(src_ptr1)          // %4 
    426   : "r"(&kMult38_Div6),     // %5 
    427     "r"(&kShuf38_2),        // %6 
    428     "r"(&kMult38_Div9)      // %7 
    429   : "q0", "q1", "q2", "q3", "q8", "q9", "q13", "q14", "q15", "memory", "cc" 
    430   ); 
     310  asm volatile( 
     311      "vld1.16    {q13}, [%5]                    \n" 
     312      "vld1.8     {q14}, [%6]                    \n" 
     313      "vld1.8     {q15}, [%7]                    \n" 
     314      "add        %3, %0                         \n" 
     315      "1:                                          \n" 
     316 
     317      // d0 = 00 40 01 41 02 42 03 43 
     318      // d1 = 10 50 11 51 12 52 13 53 
     319      // d2 = 20 60 21 61 22 62 23 63 
     320      // d3 = 30 70 31 71 32 72 33 73 
     321      "vld4.8       {d0, d1, d2, d3}, [%0]!      \n" 
     322      "vld4.8       {d4, d5, d6, d7}, [%3]!      \n" 
     323      "vld4.8       {d16, d17, d18, d19}, [%4]!  \n" 
     324      "subs         %2, %2, #12                  \n" 
     325 
     326      // Shuffle the input data around to get align the data 
     327      //  so adjacent data can be added. 0,1 - 2,3 - 4,5 - 6,7 
     328      // d0 = 00 10 01 11 02 12 03 13 
     329      // d1 = 40 50 41 51 42 52 43 53 
     330      "vtrn.u8      d0, d1                       \n" 
     331      "vtrn.u8      d4, d5                       \n" 
     332      "vtrn.u8      d16, d17                     \n" 
     333 
     334      // d2 = 20 30 21 31 22 32 23 33 
     335      // d3 = 60 70 61 71 62 72 63 73 
     336      "vtrn.u8      d2, d3                       \n" 
     337      "vtrn.u8      d6, d7                       \n" 
     338      "vtrn.u8      d18, d19                     \n" 
     339 
     340      // d0 = 00+10 01+11 02+12 03+13 
     341      // d2 = 40+50 41+51 42+52 43+53 
     342      "vpaddl.u8    q0, q0                       \n" 
     343      "vpaddl.u8    q2, q2                       \n" 
     344      "vpaddl.u8    q8, q8                       \n" 
     345 
     346      // d3 = 60+70 61+71 62+72 63+73 
     347      "vpaddl.u8    d3, d3                       \n" 
     348      "vpaddl.u8    d7, d7                       \n" 
     349      "vpaddl.u8    d19, d19                     \n" 
     350 
     351      // combine source lines 
     352      "vadd.u16     q0, q2                       \n" 
     353      "vadd.u16     q0, q8                       \n" 
     354      "vadd.u16     d4, d3, d7                   \n" 
     355      "vadd.u16     d4, d19                      \n" 
     356 
     357      // dst_ptr[3] = (s[6 + st * 0] + s[7 + st * 0] 
     358      //             + s[6 + st * 1] + s[7 + st * 1] 
     359      //             + s[6 + st * 2] + s[7 + st * 2]) / 6 
     360      "vqrdmulh.s16 q2, q2, q13                  \n" 
     361      "vmovn.u16    d4, q2                       \n" 
     362 
     363      // Shuffle 2,3 reg around so that 2 can be added to the 
     364      //  0,1 reg and 3 can be added to the 4,5 reg. This 
     365      //  requires expanding from u8 to u16 as the 0,1 and 4,5 
     366      //  registers are already expanded. Then do transposes 
     367      //  to get aligned. 
     368      // q2 = xx 20 xx 30 xx 21 xx 31 xx 22 xx 32 xx 23 xx 33 
     369      "vmovl.u8     q1, d2                       \n" 
     370      "vmovl.u8     q3, d6                       \n" 
     371      "vmovl.u8     q9, d18                      \n" 
     372 
     373      // combine source lines 
     374      "vadd.u16     q1, q3                       \n" 
     375      "vadd.u16     q1, q9                       \n" 
     376 
     377      // d4 = xx 20 xx 30 xx 22 xx 32 
     378      // d5 = xx 21 xx 31 xx 23 xx 33 
     379      "vtrn.u32     d2, d3                       \n" 
     380 
     381      // d4 = xx 20 xx 21 xx 22 xx 23 
     382      // d5 = xx 30 xx 31 xx 32 xx 33 
     383      "vtrn.u16     d2, d3                       \n" 
     384 
     385      // 0+1+2, 3+4+5 
     386      "vadd.u16     q0, q1                       \n" 
     387 
     388      // Need to divide, but can't downshift as the the value 
     389      //  isn't a power of 2. So multiply by 65536 / n 
     390      //  and take the upper 16 bits. 
     391      "vqrdmulh.s16 q0, q0, q15                  \n" 
     392 
     393      // Align for table lookup, vtbl requires registers to 
     394      //  be adjacent 
     395      "vmov.u8      d2, d4                       \n" 
     396 
     397      "vtbl.u8      d3, {d0, d1, d2}, d28        \n" 
     398      "vtbl.u8      d4, {d0, d1, d2}, d29        \n" 
     399 
     400      "vst1.8       {d3}, [%1]!                  \n" 
     401      "vst1.32      {d4[0]}, [%1]!               \n" 
     402      "bgt          1b                           \n" 
     403      : "+r"(src_ptr),       // %0 
     404        "+r"(dst_ptr),       // %1 
     405        "+r"(dst_width),     // %2 
     406        "+r"(src_stride),    // %3 
     407        "+r"(src_ptr1)       // %4 
     408      : "r"(&kMult38_Div6),  // %5 
     409        "r"(&kShuf38_2),     // %6 
     410        "r"(&kMult38_Div9)   // %7 
     411      : "q0", "q1", "q2", "q3", "q8", "q9", "q13", "q14", "q15", "memory", 
     412        "cc"); 
    431413} 
    432414 
     
    434416void ScaleRowDown38_2_Box_NEON(const uint8* src_ptr, 
    435417                               ptrdiff_t src_stride, 
    436                                uint8* dst_ptr, int dst_width) { 
    437   asm volatile ( 
    438     MEMACCESS(4) 
    439     "vld1.16    {q13}, [%4]                    \n" 
    440     MEMACCESS(5) 
    441     "vld1.8     {q14}, [%5]                    \n" 
    442     "add        %3, %0                         \n" 
    443   "1:                                          \n" 
    444  
    445     // d0 = 00 40 01 41 02 42 03 43 
    446     // d1 = 10 50 11 51 12 52 13 53 
    447     // d2 = 20 60 21 61 22 62 23 63 
    448     // d3 = 30 70 31 71 32 72 33 73 
    449     MEMACCESS(0) 
    450     "vld4.8       {d0, d1, d2, d3}, [%0]!      \n" 
    451     MEMACCESS(3) 
    452     "vld4.8       {d4, d5, d6, d7}, [%3]!      \n" 
    453     "subs         %2, %2, #12                  \n" 
    454  
    455     // Shuffle the input data around to get align the data 
    456     //  so adjacent data can be added. 0,1 - 2,3 - 4,5 - 6,7 
    457     // d0 = 00 10 01 11 02 12 03 13 
    458     // d1 = 40 50 41 51 42 52 43 53 
    459     "vtrn.u8      d0, d1                       \n" 
    460     "vtrn.u8      d4, d5                       \n" 
    461  
    462     // d2 = 20 30 21 31 22 32 23 33 
    463     // d3 = 60 70 61 71 62 72 63 73 
    464     "vtrn.u8      d2, d3                       \n" 
    465     "vtrn.u8      d6, d7                       \n" 
    466  
    467     // d0 = 00+10 01+11 02+12 03+13 
    468     // d2 = 40+50 41+51 42+52 43+53 
    469     "vpaddl.u8    q0, q0                       \n" 
    470     "vpaddl.u8    q2, q2                       \n" 
    471  
    472     // d3 = 60+70 61+71 62+72 63+73 
    473     "vpaddl.u8    d3, d3                       \n" 
    474     "vpaddl.u8    d7, d7                       \n" 
    475  
    476     // combine source lines 
    477     "vadd.u16     q0, q2                       \n" 
    478     "vadd.u16     d4, d3, d7                   \n" 
    479  
    480     // dst_ptr[3] = (s[6] + s[7] + s[6+st] + s[7+st]) / 4 
    481     "vqrshrn.u16  d4, q2, #2                   \n" 
    482  
    483     // Shuffle 2,3 reg around so that 2 can be added to the 
    484     //  0,1 reg and 3 can be added to the 4,5 reg. This 
    485     //  requires expanding from u8 to u16 as the 0,1 and 4,5 
    486     //  registers are already expanded. Then do transposes 
    487     //  to get aligned. 
    488     // q2 = xx 20 xx 30 xx 21 xx 31 xx 22 xx 32 xx 23 xx 33 
    489     "vmovl.u8     q1, d2                       \n" 
    490     "vmovl.u8     q3, d6                       \n" 
    491  
    492     // combine source lines 
    493     "vadd.u16     q1, q3                       \n" 
    494  
    495     // d4 = xx 20 xx 30 xx 22 xx 32 
    496     // d5 = xx 21 xx 31 xx 23 xx 33 
    497     "vtrn.u32     d2, d3                       \n" 
    498  
    499     // d4 = xx 20 xx 21 xx 22 xx 23 
    500     // d5 = xx 30 xx 31 xx 32 xx 33 
    501     "vtrn.u16     d2, d3                       \n" 
    502  
    503     // 0+1+2, 3+4+5 
    504     "vadd.u16     q0, q1                       \n" 
    505  
    506     // Need to divide, but can't downshift as the the value 
    507     //  isn't a power of 2. So multiply by 65536 / n 
    508     //  and take the upper 16 bits. 
    509     "vqrdmulh.s16 q0, q0, q13                  \n" 
    510  
    511     // Align for table lookup, vtbl requires registers to 
    512     //  be adjacent 
    513     "vmov.u8      d2, d4                       \n" 
    514  
    515     "vtbl.u8      d3, {d0, d1, d2}, d28        \n" 
    516     "vtbl.u8      d4, {d0, d1, d2}, d29        \n" 
    517  
    518     MEMACCESS(1) 
    519     "vst1.8       {d3}, [%1]!                  \n" 
    520     MEMACCESS(1) 
    521     "vst1.32      {d4[0]}, [%1]!               \n" 
    522     "bgt          1b                           \n" 
    523   : "+r"(src_ptr),       // %0 
    524     "+r"(dst_ptr),       // %1 
    525     "+r"(dst_width),     // %2 
    526     "+r"(src_stride)     // %3 
    527   : "r"(&kMult38_Div6),  // %4 
    528     "r"(&kShuf38_2)      // %5 
    529   : "q0", "q1", "q2", "q3", "q13", "q14", "memory", "cc" 
    530   ); 
    531 } 
    532  
    533 void ScaleAddRows_NEON(const uint8* src_ptr, ptrdiff_t src_stride, 
    534                     uint16* dst_ptr, int src_width, int src_height) { 
     418                               uint8* dst_ptr, 
     419                               int dst_width) { 
     420  asm volatile( 
     421      "vld1.16    {q13}, [%4]                    \n" 
     422      "vld1.8     {q14}, [%5]                    \n" 
     423      "add        %3, %0                         \n" 
     424      "1:                                          \n" 
     425 
     426      // d0 = 00 40 01 41 02 42 03 43 
     427      // d1 = 10 50 11 51 12 52 13 53 
     428      // d2 = 20 60 21 61 22 62 23 63 
     429      // d3 = 30 70 31 71 32 72 33 73 
     430      "vld4.8       {d0, d1, d2, d3}, [%0]!      \n" 
     431      "vld4.8       {d4, d5, d6, d7}, [%3]!      \n" 
     432      "subs         %2, %2, #12                  \n" 
     433 
     434      // Shuffle the input data around to get align the data 
     435      //  so adjacent data can be added. 0,1 - 2,3 - 4,5 - 6,7 
     436      // d0 = 00 10 01 11 02 12 03 13 
     437      // d1 = 40 50 41 51 42 52 43 53 
     438      "vtrn.u8      d0, d1                       \n" 
     439      "vtrn.u8      d4, d5                       \n" 
     440 
     441      // d2 = 20 30 21 31 22 32 23 33 
     442      // d3 = 60 70 61 71 62 72 63 73 
     443      "vtrn.u8      d2, d3                       \n" 
     444      "vtrn.u8      d6, d7                       \n" 
     445 
     446      // d0 = 00+10 01+11 02+12 03+13 
     447      // d2 = 40+50 41+51 42+52 43+53 
     448      "vpaddl.u8    q0, q0                       \n" 
     449      "vpaddl.u8    q2, q2                       \n" 
     450 
     451      // d3 = 60+70 61+71 62+72 63+73 
     452      "vpaddl.u8    d3, d3                       \n" 
     453      "vpaddl.u8    d7, d7                       \n" 
     454 
     455      // combine source lines 
     456      "vadd.u16     q0, q2                       \n" 
     457      "vadd.u16     d4, d3, d7                   \n" 
     458 
     459      // dst_ptr[3] = (s[6] + s[7] + s[6+st] + s[7+st]) / 4 
     460      "vqrshrn.u16  d4, q2, #2                   \n" 
     461 
     462      // Shuffle 2,3 reg around so that 2 can be added to the 
     463      //  0,1 reg and 3 can be added to the 4,5 reg. This 
     464      //  requires expanding from u8 to u16 as the 0,1 and 4,5 
     465      //  registers are already expanded. Then do transposes 
     466      //  to get aligned. 
     467      // q2 = xx 20 xx 30 xx 21 xx 31 xx 22 xx 32 xx 23 xx 33 
     468      "vmovl.u8     q1, d2                       \n" 
     469      "vmovl.u8     q3, d6                       \n" 
     470 
     471      // combine source lines 
     472      "vadd.u16     q1, q3                       \n" 
     473 
     474      // d4 = xx 20 xx 30 xx 22 xx 32 
     475      // d5 = xx 21 xx 31 xx 23 xx 33 
     476      "vtrn.u32     d2, d3                       \n" 
     477 
     478      // d4 = xx 20 xx 21 xx 22 xx 23 
     479      // d5 = xx 30 xx 31 xx 32 xx 33 
     480      "vtrn.u16     d2, d3                       \n" 
     481 
     482      // 0+1+2, 3+4+5 
     483      "vadd.u16     q0, q1                       \n" 
     484 
     485      // Need to divide, but can't downshift as the the value 
     486      //  isn't a power of 2. So multiply by 65536 / n 
     487      //  and take the upper 16 bits. 
     488      "vqrdmulh.s16 q0, q0, q13                  \n" 
     489 
     490      // Align for table lookup, vtbl requires registers to 
     491      //  be adjacent 
     492      "vmov.u8      d2, d4                       \n" 
     493 
     494      "vtbl.u8      d3, {d0, d1, d2}, d28        \n" 
     495      "vtbl.u8      d4, {d0, d1, d2}, d29        \n" 
     496 
     497      "vst1.8       {d3}, [%1]!                  \n" 
     498      "vst1.32      {d4[0]}, [%1]!               \n" 
     499      "bgt          1b                           \n" 
     500      : "+r"(src_ptr),       // %0 
     501        "+r"(dst_ptr),       // %1 
     502        "+r"(dst_width),     // %2 
     503        "+r"(src_stride)     // %3 
     504      : "r"(&kMult38_Div6),  // %4 
     505        "r"(&kShuf38_2)      // %5 
     506      : "q0", "q1", "q2", "q3", "q13", "q14", "memory", "cc"); 
     507} 
     508 
     509void ScaleAddRows_NEON(const uint8* src_ptr, 
     510                       ptrdiff_t src_stride, 
     511                       uint16* dst_ptr, 
     512                       int src_width, 
     513                       int src_height) { 
    535514  const uint8* src_tmp; 
    536   asm volatile ( 
    537   "1:                                          \n" 
    538     "mov       %0, %1                          \n" 
    539     "mov       r12, %5                         \n" 
    540     "veor      q2, q2, q2                      \n" 
    541     "veor      q3, q3, q3                      \n" 
    542   "2:                                          \n" 
    543     // load 16 pixels into q0 
    544     MEMACCESS(0) 
    545     "vld1.8     {q0}, [%0], %3                 \n" 
    546     "vaddw.u8   q3, q3, d1                     \n" 
    547     "vaddw.u8   q2, q2, d0                     \n" 
    548     "subs       r12, r12, #1                   \n" 
    549     "bgt        2b                             \n" 
    550     MEMACCESS(2) 
    551     "vst1.16    {q2, q3}, [%2]!                \n"  // store pixels 
    552     "add        %1, %1, #16                    \n" 
    553     "subs       %4, %4, #16                    \n"  // 16 processed per loop 
    554     "bgt        1b                             \n" 
    555   : "=&r"(src_tmp),    // %0 
    556     "+r"(src_ptr),     // %1 
    557     "+r"(dst_ptr),     // %2 
    558     "+r"(src_stride),  // %3 
    559     "+r"(src_width),   // %4 
    560     "+r"(src_height)   // %5 
    561   : 
    562   : "memory", "cc", "r12", "q0", "q1", "q2", "q3"  // Clobber List 
    563   ); 
    564 } 
    565  
     515  asm volatile( 
     516      "1:                                          \n" 
     517      "mov       %0, %1                          \n" 
     518      "mov       r12, %5                         \n" 
     519      "veor      q2, q2, q2                      \n" 
     520      "veor      q3, q3, q3                      \n" 
     521      "2:                                          \n" 
     522      // load 16 pixels into q0 
     523      "vld1.8     {q0}, [%0], %3                 \n" 
     524      "vaddw.u8   q3, q3, d1                     \n" 
     525      "vaddw.u8   q2, q2, d0                     \n" 
     526      "subs       r12, r12, #1                   \n" 
     527      "bgt        2b                             \n" 
     528      "vst1.16    {q2, q3}, [%2]!                \n"  // store pixels 
     529      "add        %1, %1, #16                    \n" 
     530      "subs       %4, %4, #16                    \n"  // 16 processed per loop 
     531      "bgt        1b                             \n" 
     532      : "=&r"(src_tmp),    // %0 
     533        "+r"(src_ptr),     // %1 
     534        "+r"(dst_ptr),     // %2 
     535        "+r"(src_stride),  // %3 
     536        "+r"(src_width),   // %4 
     537        "+r"(src_height)   // %5 
     538      : 
     539      : "memory", "cc", "r12", "q0", "q1", "q2", "q3"  // Clobber List 
     540      ); 
     541} 
     542 
     543// clang-format off 
    566544// TODO(Yang Zhang): Investigate less load instructions for 
    567545// the x/dx stepping 
     
    570548    "add        %6, %1, %5                     \n"             \ 
    571549    "add        %3, %3, %4                     \n"             \ 
    572     MEMACCESS(6)                                               \ 
    573550    "vld2.8     {d6["#n"], d7["#n"]}, [%6]     \n" 
    574  
    575 void ScaleFilterCols_NEON(uint8* dst_ptr, const uint8* src_ptr, 
    576                           int dst_width, int x, int dx) { 
     551// clang-format on 
     552 
     553// The NEON version mimics this formula (from row_common.cc): 
     554// #define BLENDER(a, b, f) (uint8)((int)(a) + 
     555//    ((((int)((f)) * ((int)(b) - (int)(a))) + 0x8000) >> 16)) 
     556 
     557void ScaleFilterCols_NEON(uint8* dst_ptr, 
     558                          const uint8* src_ptr, 
     559                          int dst_width, 
     560                          int x, 
     561                          int dx) { 
    577562  int dx_offset[4] = {0, 1, 2, 3}; 
    578563  int* tmp = dx_offset; 
     
    609594    "vmul.s32   q11, q11, q13                  \n" 
    610595    "vmul.s32   q12, q12, q10                  \n" 
    611     "vshrn.s32  d18, q11, #16                  \n" 
    612     "vshrn.s32  d19, q12, #16                  \n" 
     596    "vrshrn.s32  d18, q11, #16                 \n" 
     597    "vrshrn.s32  d19, q12, #16                 \n" 
    613598    "vadd.s16   q8, q8, q9                     \n" 
    614599    "vmovn.s16  d6, q8                         \n" 
    615600 
    616     MEMACCESS(0) 
    617601    "vst1.8     {d6}, [%0]!                    \n"  // store pixels 
    618602    "vadd.s32   q1, q1, q0                     \n" 
     
    637621// 16x2 -> 16x1 
    638622void ScaleFilterRows_NEON(uint8* dst_ptr, 
    639                           const uint8* src_ptr, ptrdiff_t src_stride, 
    640                           int dst_width, int source_y_fraction) { 
    641   asm volatile ( 
    642     "cmp          %4, #0                       \n" 
    643     "beq          100f                         \n" 
    644     "add          %2, %1                       \n" 
    645     "cmp          %4, #64                      \n" 
    646     "beq          75f                          \n" 
    647     "cmp          %4, #128                     \n" 
    648     "beq          50f                          \n" 
    649     "cmp          %4, #192                     \n" 
    650     "beq          25f                          \n" 
    651  
    652     "vdup.8       d5, %4                       \n" 
    653     "rsb          %4, #256                     \n" 
    654     "vdup.8       d4, %4                       \n" 
    655     // General purpose row blend. 
    656   "1:                                          \n" 
    657     MEMACCESS(1) 
    658     "vld1.8       {q0}, [%1]!                  \n" 
    659     MEMACCESS(2) 
    660     "vld1.8       {q1}, [%2]!                  \n" 
    661     "subs         %3, %3, #16                  \n" 
    662     "vmull.u8     q13, d0, d4                  \n" 
    663     "vmull.u8     q14, d1, d4                  \n" 
    664     "vmlal.u8     q13, d2, d5                  \n" 
    665     "vmlal.u8     q14, d3, d5                  \n" 
    666     "vrshrn.u16   d0, q13, #8                  \n" 
    667     "vrshrn.u16   d1, q14, #8                  \n" 
    668     MEMACCESS(0) 
    669     "vst1.8       {q0}, [%0]!                  \n" 
    670     "bgt          1b                           \n" 
    671     "b            99f                          \n" 
    672  
    673     // Blend 25 / 75. 
    674   "25:                                         \n" 
    675     MEMACCESS(1) 
    676     "vld1.8       {q0}, [%1]!                  \n" 
    677     MEMACCESS(2) 
    678     "vld1.8       {q1}, [%2]!                  \n" 
    679     "subs         %3, %3, #16                  \n" 
    680     "vrhadd.u8    q0, q1                       \n" 
    681     "vrhadd.u8    q0, q1                       \n" 
    682     MEMACCESS(0) 
    683     "vst1.8       {q0}, [%0]!                  \n" 
    684     "bgt          25b                          \n" 
    685     "b            99f                          \n" 
    686  
    687     // Blend 50 / 50. 
    688   "50:                                         \n" 
    689     MEMACCESS(1) 
    690     "vld1.8       {q0}, [%1]!                  \n" 
    691     MEMACCESS(2) 
    692     "vld1.8       {q1}, [%2]!                  \n" 
    693     "subs         %3, %3, #16                  \n" 
    694     "vrhadd.u8    q0, q1                       \n" 
    695     MEMACCESS(0) 
    696     "vst1.8       {q0}, [%0]!                  \n" 
    697     "bgt          50b                          \n" 
    698     "b            99f                          \n" 
    699  
    700     // Blend 75 / 25. 
    701   "75:                                         \n" 
    702     MEMACCESS(1) 
    703     "vld1.8       {q1}, [%1]!                  \n" 
    704     MEMACCESS(2) 
    705     "vld1.8       {q0}, [%2]!                  \n" 
    706     "subs         %3, %3, #16                  \n" 
    707     "vrhadd.u8    q0, q1                       \n" 
    708     "vrhadd.u8    q0, q1                       \n" 
    709     MEMACCESS(0) 
    710     "vst1.8       {q0}, [%0]!                  \n" 
    711     "bgt          75b                          \n" 
    712     "b            99f                          \n" 
    713  
    714     // Blend 100 / 0 - Copy row unchanged. 
    715   "100:                                        \n" 
    716     MEMACCESS(1) 
    717     "vld1.8       {q0}, [%1]!                  \n" 
    718     "subs         %3, %3, #16                  \n" 
    719     MEMACCESS(0) 
    720     "vst1.8       {q0}, [%0]!                  \n" 
    721     "bgt          100b                         \n" 
    722  
    723   "99:                                         \n" 
    724     MEMACCESS(0) 
    725     "vst1.8       {d1[7]}, [%0]                \n" 
    726   : "+r"(dst_ptr),          // %0 
    727     "+r"(src_ptr),          // %1 
    728     "+r"(src_stride),       // %2 
    729     "+r"(dst_width),        // %3 
    730     "+r"(source_y_fraction) // %4 
    731   : 
    732   : "q0", "q1", "d4", "d5", "q13", "q14", "memory", "cc" 
    733   ); 
    734 } 
    735  
    736 void ScaleARGBRowDown2_NEON(const uint8* src_ptr, ptrdiff_t src_stride, 
    737                             uint8* dst, int dst_width) { 
    738   asm volatile ( 
    739   "1:                                          \n" 
    740     // load even pixels into q0, odd into q1 
    741     MEMACCESS(0) 
    742     "vld2.32    {q0, q1}, [%0]!                \n" 
    743     MEMACCESS(0) 
    744     "vld2.32    {q2, q3}, [%0]!                \n" 
    745     "subs       %2, %2, #8                     \n"  // 8 processed per loop 
    746     MEMACCESS(1) 
    747     "vst1.8     {q1}, [%1]!                    \n"  // store odd pixels 
    748     MEMACCESS(1) 
    749     "vst1.8     {q3}, [%1]!                    \n" 
    750     "bgt        1b                             \n" 
    751   : "+r"(src_ptr),          // %0 
    752     "+r"(dst),              // %1 
    753     "+r"(dst_width)         // %2 
    754   : 
    755   : "memory", "cc", "q0", "q1", "q2", "q3"  // Clobber List 
    756   ); 
    757 } 
    758  
    759 void ScaleARGBRowDown2Linear_NEON(const uint8* src_argb, ptrdiff_t src_stride, 
    760                                   uint8* dst_argb, int dst_width) { 
    761   asm volatile ( 
    762   "1:                                          \n" 
    763     MEMACCESS(0) 
    764     "vld4.8     {d0, d2, d4, d6}, [%0]!        \n"  // load 8 ARGB pixels. 
    765     MEMACCESS(0) 
    766     "vld4.8     {d1, d3, d5, d7}, [%0]!        \n"  // load next 8 ARGB pixels. 
    767     "subs       %2, %2, #8                     \n"  // 8 processed per loop 
    768     "vpaddl.u8  q0, q0                         \n"  // B 16 bytes -> 8 shorts. 
    769     "vpaddl.u8  q1, q1                         \n"  // G 16 bytes -> 8 shorts. 
    770     "vpaddl.u8  q2, q2                         \n"  // R 16 bytes -> 8 shorts. 
    771     "vpaddl.u8  q3, q3                         \n"  // A 16 bytes -> 8 shorts. 
    772     "vrshrn.u16 d0, q0, #1                     \n"  // downshift, round and pack 
    773     "vrshrn.u16 d1, q1, #1                     \n" 
    774     "vrshrn.u16 d2, q2, #1                     \n" 
    775     "vrshrn.u16 d3, q3, #1                     \n" 
    776     MEMACCESS(1) 
    777     "vst4.8     {d0, d1, d2, d3}, [%1]!        \n" 
    778     "bgt       1b                              \n" 
    779   : "+r"(src_argb),         // %0 
    780     "+r"(dst_argb),         // %1 
    781     "+r"(dst_width)         // %2 
    782   : 
    783   : "memory", "cc", "q0", "q1", "q2", "q3"     // Clobber List 
    784   ); 
    785 } 
    786  
    787 void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, ptrdiff_t src_stride, 
    788                                uint8* dst, int dst_width) { 
    789   asm volatile ( 
    790     // change the stride to row 2 pointer 
    791     "add        %1, %1, %0                     \n" 
    792   "1:                                          \n" 
    793     MEMACCESS(0) 
    794     "vld4.8     {d0, d2, d4, d6}, [%0]!        \n"  // load 8 ARGB pixels. 
    795     MEMACCESS(0) 
    796     "vld4.8     {d1, d3, d5, d7}, [%0]!        \n"  // load next 8 ARGB pixels. 
    797     "subs       %3, %3, #8                     \n"  // 8 processed per loop. 
    798     "vpaddl.u8  q0, q0                         \n"  // B 16 bytes -> 8 shorts. 
    799     "vpaddl.u8  q1, q1                         \n"  // G 16 bytes -> 8 shorts. 
    800     "vpaddl.u8  q2, q2                         \n"  // R 16 bytes -> 8 shorts. 
    801     "vpaddl.u8  q3, q3                         \n"  // A 16 bytes -> 8 shorts. 
    802     MEMACCESS(1) 
    803     "vld4.8     {d16, d18, d20, d22}, [%1]!    \n"  // load 8 more ARGB pixels. 
    804     MEMACCESS(1) 
    805     "vld4.8     {d17, d19, d21, d23}, [%1]!    \n"  // load last 8 ARGB pixels. 
    806     "vpadal.u8  q0, q8                         \n"  // B 16 bytes -> 8 shorts. 
    807     "vpadal.u8  q1, q9                         \n"  // G 16 bytes -> 8 shorts. 
    808     "vpadal.u8  q2, q10                        \n"  // R 16 bytes -> 8 shorts. 
    809     "vpadal.u8  q3, q11                        \n"  // A 16 bytes -> 8 shorts. 
    810     "vrshrn.u16 d0, q0, #2                     \n"  // downshift, round and pack 
    811     "vrshrn.u16 d1, q1, #2                     \n" 
    812     "vrshrn.u16 d2, q2, #2                     \n" 
    813     "vrshrn.u16 d3, q3, #2                     \n" 
    814     MEMACCESS(2) 
    815     "vst4.8     {d0, d1, d2, d3}, [%2]!        \n" 
    816     "bgt        1b                             \n" 
    817   : "+r"(src_ptr),          // %0 
    818     "+r"(src_stride),       // %1 
    819     "+r"(dst),              // %2 
    820     "+r"(dst_width)         // %3 
    821   : 
    822   : "memory", "cc", "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11" 
    823   ); 
     623                          const uint8* src_ptr, 
     624                          ptrdiff_t src_stride, 
     625                          int dst_width, 
     626                          int source_y_fraction) { 
     627  asm volatile( 
     628      "cmp          %4, #0                       \n" 
     629      "beq          100f                         \n" 
     630      "add          %2, %1                       \n" 
     631      "cmp          %4, #64                      \n" 
     632      "beq          75f                          \n" 
     633      "cmp          %4, #128                     \n" 
     634      "beq          50f                          \n" 
     635      "cmp          %4, #192                     \n" 
     636      "beq          25f                          \n" 
     637 
     638      "vdup.8       d5, %4                       \n" 
     639      "rsb          %4, #256                     \n" 
     640      "vdup.8       d4, %4                       \n" 
     641      // General purpose row blend. 
     642      "1:                                          \n" 
     643      "vld1.8       {q0}, [%1]!                  \n" 
     644      "vld1.8       {q1}, [%2]!                  \n" 
     645      "subs         %3, %3, #16                  \n" 
     646      "vmull.u8     q13, d0, d4                  \n" 
     647      "vmull.u8     q14, d1, d4                  \n" 
     648      "vmlal.u8     q13, d2, d5                  \n" 
     649      "vmlal.u8     q14, d3, d5                  \n" 
     650      "vrshrn.u16   d0, q13, #8                  \n" 
     651      "vrshrn.u16   d1, q14, #8                  \n" 
     652      "vst1.8       {q0}, [%0]!                  \n" 
     653      "bgt          1b                           \n" 
     654      "b            99f                          \n" 
     655 
     656      // Blend 25 / 75. 
     657      "25:                                         \n" 
     658      "vld1.8       {q0}, [%1]!                  \n" 
     659      "vld1.8       {q1}, [%2]!                  \n" 
     660      "subs         %3, %3, #16                  \n" 
     661      "vrhadd.u8    q0, q1                       \n" 
     662      "vrhadd.u8    q0, q1                       \n" 
     663      "vst1.8       {q0}, [%0]!                  \n" 
     664      "bgt          25b                          \n" 
     665      "b            99f                          \n" 
     666 
     667      // Blend 50 / 50. 
     668      "50:                                         \n" 
     669      "vld1.8       {q0}, [%1]!                  \n" 
     670      "vld1.8       {q1}, [%2]!                  \n" 
     671      "subs         %3, %3, #16                  \n" 
     672      "vrhadd.u8    q0, q1                       \n" 
     673      "vst1.8       {q0}, [%0]!                  \n" 
     674      "bgt          50b                          \n" 
     675      "b            99f                          \n" 
     676 
     677      // Blend 75 / 25. 
     678      "75:                                         \n" 
     679      "vld1.8       {q1}, [%1]!                  \n" 
     680      "vld1.8       {q0}, [%2]!                  \n" 
     681      "subs         %3, %3, #16                  \n" 
     682      "vrhadd.u8    q0, q1                       \n" 
     683      "vrhadd.u8    q0, q1                       \n" 
     684      "vst1.8       {q0}, [%0]!                  \n" 
     685      "bgt          75b                          \n" 
     686      "b            99f                          \n" 
     687 
     688      // Blend 100 / 0 - Copy row unchanged. 
     689      "100:                                        \n" 
     690      "vld1.8       {q0}, [%1]!                  \n" 
     691      "subs         %3, %3, #16                  \n" 
     692      "vst1.8       {q0}, [%0]!                  \n" 
     693      "bgt          100b                         \n" 
     694 
     695      "99:                                         \n" 
     696      "vst1.8       {d1[7]}, [%0]                \n" 
     697      : "+r"(dst_ptr),           // %0 
     698        "+r"(src_ptr),           // %1 
     699        "+r"(src_stride),        // %2 
     700        "+r"(dst_width),         // %3 
     701        "+r"(source_y_fraction)  // %4 
     702      : 
     703      : "q0", "q1", "d4", "d5", "q13", "q14", "memory", "cc"); 
     704} 
     705 
     706void ScaleARGBRowDown2_NEON(const uint8* src_ptr, 
     707                            ptrdiff_t src_stride, 
     708                            uint8* dst, 
     709                            int dst_width) { 
     710  (void)src_stride; 
     711  asm volatile( 
     712      "1:                                          \n" 
     713      // load even pixels into q0, odd into q1 
     714      "vld2.32    {q0, q1}, [%0]!                \n" 
     715      "vld2.32    {q2, q3}, [%0]!                \n" 
     716      "subs       %2, %2, #8                     \n"  // 8 processed per loop 
     717      "vst1.8     {q1}, [%1]!                    \n"  // store odd pixels 
     718      "vst1.8     {q3}, [%1]!                    \n" 
     719      "bgt        1b                             \n" 
     720      : "+r"(src_ptr),   // %0 
     721        "+r"(dst),       // %1 
     722        "+r"(dst_width)  // %2 
     723      : 
     724      : "memory", "cc", "q0", "q1", "q2", "q3"  // Clobber List 
     725      ); 
     726} 
     727 
     728void ScaleARGBRowDown2Linear_NEON(const uint8* src_argb, 
     729                                  ptrdiff_t src_stride, 
     730                                  uint8* dst_argb, 
     731                                  int dst_width) { 
     732  (void)src_stride; 
     733  asm volatile( 
     734      "1:                                          \n" 
     735      "vld4.8     {d0, d2, d4, d6}, [%0]!        \n"  // load 8 ARGB pixels. 
     736      "vld4.8     {d1, d3, d5, d7}, [%0]!        \n"  // load next 8 ARGB 
     737                                                      // pixels. 
     738      "subs       %2, %2, #8                     \n"  // 8 processed per loop 
     739      "vpaddl.u8  q0, q0                         \n"  // B 16 bytes -> 8 shorts. 
     740      "vpaddl.u8  q1, q1                         \n"  // G 16 bytes -> 8 shorts. 
     741      "vpaddl.u8  q2, q2                         \n"  // R 16 bytes -> 8 shorts. 
     742      "vpaddl.u8  q3, q3                         \n"  // A 16 bytes -> 8 shorts. 
     743      "vrshrn.u16 d0, q0, #1                     \n"  // downshift, round and 
     744                                                      // pack 
     745      "vrshrn.u16 d1, q1, #1                     \n" 
     746      "vrshrn.u16 d2, q2, #1                     \n" 
     747      "vrshrn.u16 d3, q3, #1                     \n" 
     748      "vst4.8     {d0, d1, d2, d3}, [%1]!        \n" 
     749      "bgt       1b                              \n" 
     750      : "+r"(src_argb),  // %0 
     751        "+r"(dst_argb),  // %1 
     752        "+r"(dst_width)  // %2 
     753      : 
     754      : "memory", "cc", "q0", "q1", "q2", "q3"  // Clobber List 
     755      ); 
     756} 
     757 
     758void ScaleARGBRowDown2Box_NEON(const uint8* src_ptr, 
     759                               ptrdiff_t src_stride, 
     760                               uint8* dst, 
     761                               int dst_width) { 
     762  asm volatile( 
     763      // change the stride to row 2 pointer 
     764      "add        %1, %1, %0                     \n" 
     765      "1:                                          \n" 
     766      "vld4.8     {d0, d2, d4, d6}, [%0]!        \n"  // load 8 ARGB pixels. 
     767      "vld4.8     {d1, d3, d5, d7}, [%0]!        \n"  // load next 8 ARGB 
     768                                                      // pixels. 
     769      "subs       %3, %3, #8                     \n"  // 8 processed per loop. 
     770      "vpaddl.u8  q0, q0                         \n"  // B 16 bytes -> 8 shorts. 
     771      "vpaddl.u8  q1, q1                         \n"  // G 16 bytes -> 8 shorts. 
     772      "vpaddl.u8  q2, q2                         \n"  // R 16 bytes -> 8 shorts. 
     773      "vpaddl.u8  q3, q3                         \n"  // A 16 bytes -> 8 shorts. 
     774      "vld4.8     {d16, d18, d20, d22}, [%1]!    \n"  // load 8 more ARGB 
     775                                                      // pixels. 
     776      "vld4.8     {d17, d19, d21, d23}, [%1]!    \n"  // load last 8 ARGB 
     777                                                      // pixels. 
     778      "vpadal.u8  q0, q8                         \n"  // B 16 bytes -> 8 shorts. 
     779      "vpadal.u8  q1, q9                         \n"  // G 16 bytes -> 8 shorts. 
     780      "vpadal.u8  q2, q10                        \n"  // R 16 bytes -> 8 shorts. 
     781      "vpadal.u8  q3, q11                        \n"  // A 16 bytes -> 8 shorts. 
     782      "vrshrn.u16 d0, q0, #2                     \n"  // downshift, round and 
     783                                                      // pack 
     784      "vrshrn.u16 d1, q1, #2                     \n" 
     785      "vrshrn.u16 d2, q2, #2                     \n" 
     786      "vrshrn.u16 d3, q3, #2                     \n" 
     787      "vst4.8     {d0, d1, d2, d3}, [%2]!        \n" 
     788      "bgt        1b                             \n" 
     789      : "+r"(src_ptr),     // %0 
     790        "+r"(src_stride),  // %1 
     791        "+r"(dst),         // %2 
     792        "+r"(dst_width)    // %3 
     793      : 
     794      : "memory", "cc", "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11"); 
    824795} 
    825796 
    826797// Reads 4 pixels at a time. 
    827798// Alignment requirement: src_argb 4 byte aligned. 
    828 void ScaleARGBRowDownEven_NEON(const uint8* src_argb,  ptrdiff_t src_stride, 
    829                                int src_stepx, uint8* dst_argb, int dst_width) { 
    830   asm volatile ( 
    831     "mov        r12, %3, lsl #2                \n" 
    832   "1:                                          \n" 
    833     MEMACCESS(0) 
    834     "vld1.32    {d0[0]}, [%0], r12             \n" 
    835     MEMACCESS(0) 
    836     "vld1.32    {d0[1]}, [%0], r12             \n" 
    837     MEMACCESS(0) 
    838     "vld1.32    {d1[0]}, [%0], r12             \n" 
    839     MEMACCESS(0) 
    840     "vld1.32    {d1[1]}, [%0], r12             \n" 
    841     "subs       %2, %2, #4                     \n"  // 4 pixels per loop. 
    842     MEMACCESS(1) 
    843     "vst1.8     {q0}, [%1]!                    \n" 
    844     "bgt        1b                             \n" 
    845   : "+r"(src_argb),    // %0 
    846     "+r"(dst_argb),    // %1 
    847     "+r"(dst_width)    // %2 
    848   : "r"(src_stepx)     // %3 
    849   : "memory", "cc", "r12", "q0" 
    850   ); 
     799void ScaleARGBRowDownEven_NEON(const uint8* src_argb, 
     800                               ptrdiff_t src_stride, 
     801                               int src_stepx, 
     802                               uint8* dst_argb, 
     803                               int dst_width) { 
     804  (void)src_stride; 
     805  asm volatile( 
     806      "mov        r12, %3, lsl #2                \n" 
     807      "1:                                          \n" 
     808      "vld1.32    {d0[0]}, [%0], r12             \n" 
     809      "vld1.32    {d0[1]}, [%0], r12             \n" 
     810      "vld1.32    {d1[0]}, [%0], r12             \n" 
     811      "vld1.32    {d1[1]}, [%0], r12             \n" 
     812      "subs       %2, %2, #4                     \n"  // 4 pixels per loop. 
     813      "vst1.8     {q0}, [%1]!                    \n" 
     814      "bgt        1b                             \n" 
     815      : "+r"(src_argb),  // %0 
     816        "+r"(dst_argb),  // %1 
     817        "+r"(dst_width)  // %2 
     818      : "r"(src_stepx)   // %3 
     819      : "memory", "cc", "r12", "q0"); 
    851820} 
    852821 
    853822// Reads 4 pixels at a time. 
    854823// Alignment requirement: src_argb 4 byte aligned. 
    855 void ScaleARGBRowDownEvenBox_NEON(const uint8* src_argb, ptrdiff_t src_stride, 
     824void ScaleARGBRowDownEvenBox_NEON(const uint8* src_argb, 
     825                                  ptrdiff_t src_stride, 
    856826                                  int src_stepx, 
    857                                   uint8* dst_argb, int dst_width) { 
    858   asm volatile ( 
    859     "mov        r12, %4, lsl #2                \n" 
    860     "add        %1, %1, %0                     \n" 
    861   "1:                                          \n" 
    862     MEMACCESS(0) 
    863     "vld1.8     {d0}, [%0], r12                \n"  // Read 4 2x2 blocks -> 2x1 
    864     MEMACCESS(1) 
    865     "vld1.8     {d1}, [%1], r12                \n" 
    866     MEMACCESS(0) 
    867     "vld1.8     {d2}, [%0], r12                \n" 
    868     MEMACCESS(1) 
    869     "vld1.8     {d3}, [%1], r12                \n" 
    870     MEMACCESS(0) 
    871     "vld1.8     {d4}, [%0], r12                \n" 
    872     MEMACCESS(1) 
    873     "vld1.8     {d5}, [%1], r12                \n" 
    874     MEMACCESS(0) 
    875     "vld1.8     {d6}, [%0], r12                \n" 
    876     MEMACCESS(1) 
    877     "vld1.8     {d7}, [%1], r12                \n" 
    878     "vaddl.u8   q0, d0, d1                     \n" 
    879     "vaddl.u8   q1, d2, d3                     \n" 
    880     "vaddl.u8   q2, d4, d5                     \n" 
    881     "vaddl.u8   q3, d6, d7                     \n" 
    882     "vswp.8     d1, d2                         \n"  // ab_cd -> ac_bd 
    883     "vswp.8     d5, d6                         \n"  // ef_gh -> eg_fh 
    884     "vadd.u16   q0, q0, q1                     \n"  // (a+b)_(c+d) 
    885     "vadd.u16   q2, q2, q3                     \n"  // (e+f)_(g+h) 
    886     "vrshrn.u16 d0, q0, #2                     \n"  // first 2 pixels. 
    887     "vrshrn.u16 d1, q2, #2                     \n"  // next 2 pixels. 
    888     "subs       %3, %3, #4                     \n"  // 4 pixels per loop. 
    889     MEMACCESS(2) 
    890     "vst1.8     {q0}, [%2]!                    \n" 
    891     "bgt        1b                             \n" 
    892   : "+r"(src_argb),    // %0 
    893     "+r"(src_stride),  // %1 
    894     "+r"(dst_argb),    // %2 
    895     "+r"(dst_width)    // %3 
    896   : "r"(src_stepx)     // %4 
    897   : "memory", "cc", "r12", "q0", "q1", "q2", "q3" 
    898   ); 
    899 } 
    900  
     827                                  uint8* dst_argb, 
     828                                  int dst_width) { 
     829  asm volatile( 
     830      "mov        r12, %4, lsl #2                \n" 
     831      "add        %1, %1, %0                     \n" 
     832      "1:                                          \n" 
     833      "vld1.8     {d0}, [%0], r12                \n"  // Read 4 2x2 blocks -> 
     834                                                      // 2x1 
     835      "vld1.8     {d1}, [%1], r12                \n" 
     836      "vld1.8     {d2}, [%0], r12                \n" 
     837      "vld1.8     {d3}, [%1], r12                \n" 
     838      "vld1.8     {d4}, [%0], r12                \n" 
     839      "vld1.8     {d5}, [%1], r12                \n" 
     840      "vld1.8     {d6}, [%0], r12                \n" 
     841      "vld1.8     {d7}, [%1], r12                \n" 
     842      "vaddl.u8   q0, d0, d1                     \n" 
     843      "vaddl.u8   q1, d2, d3                     \n" 
     844      "vaddl.u8   q2, d4, d5                     \n" 
     845      "vaddl.u8   q3, d6, d7                     \n" 
     846      "vswp.8     d1, d2                         \n"  // ab_cd -> ac_bd 
     847      "vswp.8     d5, d6                         \n"  // ef_gh -> eg_fh 
     848      "vadd.u16   q0, q0, q1                     \n"  // (a+b)_(c+d) 
     849      "vadd.u16   q2, q2, q3                     \n"  // (e+f)_(g+h) 
     850      "vrshrn.u16 d0, q0, #2                     \n"  // first 2 pixels. 
     851      "vrshrn.u16 d1, q2, #2                     \n"  // next 2 pixels. 
     852      "subs       %3, %3, #4                     \n"  // 4 pixels per loop. 
     853      "vst1.8     {q0}, [%2]!                    \n" 
     854      "bgt        1b                             \n" 
     855      : "+r"(src_argb),    // %0 
     856        "+r"(src_stride),  // %1 
     857        "+r"(dst_argb),    // %2 
     858        "+r"(dst_width)    // %3 
     859      : "r"(src_stepx)     // %4 
     860      : "memory", "cc", "r12", "q0", "q1", "q2", "q3"); 
     861} 
     862 
     863// clang-format off 
    901864// TODO(Yang Zhang): Investigate less load instructions for 
    902865// the x/dx stepping 
    903 #define LOAD1_DATA32_LANE(dn, n)                               \ 
    904     "lsr        %5, %3, #16                    \n"             \ 
    905     "add        %6, %1, %5, lsl #2             \n"             \ 
    906     "add        %3, %3, %4                     \n"             \ 
    907     MEMACCESS(6)                                               \ 
    908     "vld1.32    {"#dn"["#n"]}, [%6]            \n" 
    909  
    910 void ScaleARGBCols_NEON(uint8* dst_argb, const uint8* src_argb, 
    911                         int dst_width, int x, int dx) { 
     866#define LOAD1_DATA32_LANE(dn, n)                            \ 
     867  "lsr        %5, %3, #16                    \n"            \ 
     868  "add        %6, %1, %5, lsl #2             \n"            \ 
     869  "add        %3, %3, %4                     \n"            \ 
     870  "vld1.32    {" #dn "[" #n "]}, [%6]        \n" 
     871// clang-format on 
     872 
     873void ScaleARGBCols_NEON(uint8* dst_argb, 
     874                        const uint8* src_argb, 
     875                        int dst_width, 
     876                        int x, 
     877                        int dx) { 
    912878  int tmp; 
    913879  const uint8* src_tmp = src_argb; 
    914   asm volatile ( 
    915   "1:                                          \n" 
    916     LOAD1_DATA32_LANE(d0, 0) 
    917     LOAD1_DATA32_LANE(d0, 1) 
    918     LOAD1_DATA32_LANE(d1, 0) 
    919     LOAD1_DATA32_LANE(d1, 1) 
    920     LOAD1_DATA32_LANE(d2, 0) 
    921     LOAD1_DATA32_LANE(d2, 1) 
    922     LOAD1_DATA32_LANE(d3, 0) 
    923     LOAD1_DATA32_LANE(d3, 1) 
    924  
    925     MEMACCESS(0) 
    926     "vst1.32     {q0, q1}, [%0]!               \n"  // store pixels 
    927     "subs       %2, %2, #8                     \n"  // 8 processed per loop 
    928     "bgt        1b                             \n" 
    929   : "+r"(dst_argb),   // %0 
    930     "+r"(src_argb),   // %1 
    931     "+r"(dst_width),  // %2 
    932     "+r"(x),          // %3 
    933     "+r"(dx),         // %4 
    934     "=&r"(tmp),       // %5 
    935     "+r"(src_tmp)     // %6 
    936   : 
    937   : "memory", "cc", "q0", "q1" 
    938   ); 
     880  asm volatile( 
     881      "1:                                          \n" LOAD1_DATA32_LANE( 
     882          d0, 0) LOAD1_DATA32_LANE(d0, 1) LOAD1_DATA32_LANE(d1, 0) 
     883          LOAD1_DATA32_LANE(d1, 1) LOAD1_DATA32_LANE(d2, 0) LOAD1_DATA32_LANE( 
     884              d2, 1) LOAD1_DATA32_LANE(d3, 0) LOAD1_DATA32_LANE(d3, 1) 
     885 
     886              "vst1.32     {q0, q1}, [%0]!               \n"  // store pixels 
     887              "subs       %2, %2, #8                     \n"  // 8 processed per 
     888                                                              // loop 
     889              "bgt        1b                             \n" 
     890      : "+r"(dst_argb),   // %0 
     891        "+r"(src_argb),   // %1 
     892        "+r"(dst_width),  // %2 
     893        "+r"(x),          // %3 
     894        "+r"(dx),         // %4 
     895        "=&r"(tmp),       // %5 
     896        "+r"(src_tmp)     // %6 
     897      : 
     898      : "memory", "cc", "q0", "q1"); 
    939899} 
    940900 
    941901#undef LOAD1_DATA32_LANE 
    942902 
     903// clang-format off 
    943904// TODO(Yang Zhang): Investigate less load instructions for 
    944905// the x/dx stepping 
    945 #define LOAD2_DATA32_LANE(dn1, dn2, n)                         \ 
    946     "lsr        %5, %3, #16                           \n"      \ 
    947     "add        %6, %1, %5, lsl #2                    \n"      \ 
    948     "add        %3, %3, %4                            \n"      \ 
    949     MEMACCESS(6)                                               \ 
    950     "vld2.32    {"#dn1"["#n"], "#dn2"["#n"]}, [%6]    \n" 
    951  
    952 void ScaleARGBFilterCols_NEON(uint8* dst_argb, const uint8* src_argb, 
    953                               int dst_width, int x, int dx) { 
     906#define LOAD2_DATA32_LANE(dn1, dn2, n)                             \ 
     907  "lsr        %5, %3, #16                           \n"            \ 
     908  "add        %6, %1, %5, lsl #2                    \n"            \ 
     909  "add        %3, %3, %4                            \n"            \ 
     910  "vld2.32    {" #dn1 "[" #n "], " #dn2 "[" #n "]}, [%6]    \n" 
     911// clang-format on 
     912 
     913void ScaleARGBFilterCols_NEON(uint8* dst_argb, 
     914                              const uint8* src_argb, 
     915                              int dst_width, 
     916                              int x, 
     917                              int dx) { 
    954918  int dx_offset[4] = {0, 1, 2, 3}; 
    955919  int* tmp = dx_offset; 
     
    990954    "vshrn.i16   d1, q12, #7                   \n" 
    991955 
    992     MEMACCESS(0) 
    993956    "vst1.32     {d0, d1}, [%0]!               \n"  // store pixels 
    994957    "vadd.s32    q8, q8, q9                    \n" 
Note: See TracChangeset for help on using the changeset viewer.