1//******************************************************************************
2//*
3//* Copyright (C) 2015 The Android Open Source Project
4//*
5//* Licensed under the Apache License, Version 2.0 (the "License");
6//* you may not use this file except in compliance with the License.
7//* You may obtain a copy of the License at:
8//*
9//* http://www.apache.org/licenses/LICENSE-2.0
10//*
11//* Unless required by applicable law or agreed to in writing, software
12//* distributed under the License is distributed on an "AS IS" BASIS,
13//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14//* See the License for the specific language governing permissions and
15//* limitations under the License.
16//*
17//*****************************************************************************
18//* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19//*/
20///**
21//******************************************************************************
22//* @file
23//*  ih264_weighted_bi_pred_av8.s
24//*
25//* @brief
26//*  Contains function definitions for weighted biprediction.
27//*
28//* @author
29//*  Kaushik Senthoor R
30//*
31//* @par List of Functions:
32//*
33//*  - ih264_weighted_bi_pred_luma_av8()
34//*  - ih264_weighted_bi_pred_chroma_av8()
35//*
36//* @remarks
37//*  None
38//*
39//*******************************************************************************
40//*/
41//*******************************************************************************
42//* @function
43//*  ih264_weighted_bi_pred_luma_av8()
44//*
45//* @brief
46//*  This routine performs the default weighted prediction as described in sec
47//* 8.4.2.3.2 titled "Weighted sample prediction process" for luma.
48//*
49//* @par Description:
50//*  This function gets two ht x wd blocks, calculates the weighted samples,
51//* rounds off, adds offset and stores it in the destination block.
52//*
53//* @param[in] puc_src1
54//*  UWORD8 Pointer to the buffer containing the input block 1.
55//*
56//* @param[in] puc_src2
57//*  UWORD8 Pointer to the buffer containing the input block 2.
58//*
59//* @param[out] puc_dst
60//*  UWORD8 pointer to the destination where the output block is stored.
61//*
62//* @param[in] src_strd1
63//*  Stride of the input buffer 1
64//*
65//* @param[in] src_strd2
66//*  Stride of the input buffer 2
67//*
68//* @param[in] dst_strd
69//*  Stride of the destination buffer
70//*
71//* @param[in] log_WD
72//*  number of bits to be rounded off
73//*
74//* @param[in] wt1
75//*  weight for the weighted prediction
76//*
77//* @param[in] wt2
78//*  weight for the weighted prediction
79//*
80//* @param[in] ofst1
81//*  offset 1 used after rounding off
82//*
83//* @param[in] ofst2
84//*  offset 2 used after rounding off
85//*
86//* @param[in] ht
87//*  integer height of the array
88//*
89//* @param[in] wd
90//*  integer width of the array
91//*
92//* @returns
93//*  None
94//*
95//* @remarks
96//*  (ht,wd) can be (4,4), (4,8), (8,4), (8,8), (8,16), (16,8) or (16,16).
97//*
98//*******************************************************************************
99//*/
100//void ih264_weighted_bi_pred_luma_av8(UWORD8 *puc_src1,
101//                                     UWORD8 *puc_src2,
102//                                     UWORD8 *puc_dst,
103//                                     WORD32 src_strd1,
104//                                     WORD32 src_strd2,
105//                                     WORD32 dst_strd,
106//                                     WORD32 log_WD,
107//                                     WORD32 wt1,
108//                                     WORD32 wt2,
109//                                     WORD16 ofst1,
110//                                     WORD16 ofst2,
111//                                     WORD32 ht,
112//                                     WORD32 wd)
113//
114//**************Variables Vs Registers*****************************************
115//    x0      => puc_src1
116//    x1      => puc_src2
117//    x2      => puc_dst
118//    w3      => src_strd1
119//    w4      => src_strd2
120//    w5      => dst_strd
121//    w6      => log_WD
122//    w7      => wt1
123//    [sp]    => wt2       (w8)
124//    [sp+8]  => ofst1     (w9)
125//    [sp+16] => ofst2     (w10)
126//    [sp+24] => ht        (w11)
127//    [sp+32] => wd        (w12)
128//
129.text
130.p2align 2
131.include "ih264_neon_macros.s"
132
133
134
135    .global ih264_weighted_bi_pred_luma_av8
136
137ih264_weighted_bi_pred_luma_av8:
138
139    // STMFD sp!, {x4-x12,x14}                //stack stores the values of the arguments
140    push_v_regs
141    sxtw      x3, w3
142    sxtw      x4, w4
143    sxtw      x5, w5
144    stp       x19, x20, [sp, #-16]!
145    ldr       w8, [sp, #80]             //Load wt2 in w8
146    ldr       w9, [sp, #88]             //Load ofst1 in w9
147    add       w6, w6, #1                //w6  = log_WD + 1
148    neg       w10, w6                   //w10 = -(log_WD + 1)
149    dup       v0.8h, w10                //Q0  = -(log_WD + 1) (32-bit)
150    ldr       w10, [sp, #96]            //Load ofst2 in w10
151    ldr       w11, [sp, #104]           //Load ht in w11
152    ldr       w12, [sp, #112]           //Load wd in w12
153    add       w9, w9, #1                //w9 = ofst1 + 1
154    add       w9, w9, w10               //w9 = ofst1 + ofst2 + 1
155    mov       v2.s[0], w7
156    mov       v2.s[1], w8               //D2 = {wt1(32-bit), wt2(32-bit)}
157    asr       w9, w9, #1                //w9 = ofst = (ofst1 + ofst2 + 1) >> 1
158    dup       v3.8b, w9                 //D3 = ofst (8-bit)
159    cmp       w12, #16
160    beq       loop_16                   //branch if wd is 16
161    cmp       w12, #8                   //check if wd is 8
162    beq       loop_8                    //branch if wd is 8
163
164loop_4:                                 //each iteration processes four rows
165
166    ld1       {v4.s}[0], [x0], x3       //load row 1 in source 1
167    ld1       {v4.s}[1], [x0], x3       //load row 2 in source 1
168    ld1       {v6.s}[0], [x1], x4       //load row 1 in source 2
169    ld1       {v6.s}[1], [x1], x4       //load row 2 in source 2
170    uxtl      v4.8h, v4.8b              //converting rows 1,2 in source 1 to 16-bit
171    ld1       {v8.s}[0], [x0], x3       //load row 3 in source 1
172    ld1       {v8.s}[1], [x0], x3       //load row 4 in source 1
173    uxtl      v6.8h, v6.8b              //converting rows 1,2 in source 2 to 16-bit
174    ld1       {v10.s}[0], [x1], x4      //load row 3 in source 2
175    ld1       {v10.s}[1], [x1], x4      //load row 4 in source 2
176    uxtl      v8.8h, v8.8b              //converting rows 3,4 in source 1 to 16-bit
177    uxtl      v10.8h, v10.8b            //converting rows 3,4 in source 2 to 16-bit
178    mul       v4.8h, v4.8h , v2.h[0]    //weight 1 mult. for rows 1,2
179    mla       v4.8h, v6.8h , v2.h[2]    //weight 2 mult. for rows 1,2
180    mul       v8.8h, v8.8h , v2.h[0]    //weight 1 mult. for rows 3,4
181    mla       v8.8h, v10.8h , v2.h[2]   //weight 2 mult. for rows 3,4
182    subs      w11, w11, #4              //decrement ht by 4
183    srshl     v4.8h, v4.8h , v0.8h      //rounds off the weighted samples from rows 1,2
184    srshl     v8.8h, v8.8h , v0.8h      //rounds off the weighted samples from rows 3,4
185    saddw     v4.8h, v4.8h , v3.8b      //adding offset for rows 1,2
186    saddw     v8.8h, v8.8h , v3.8b      //adding offset for rows 3,4
187    sqxtun    v4.8b, v4.8h              //saturating rows 1,2 to unsigned 8-bit
188    sqxtun    v8.8b, v8.8h              //saturating rows 3,4 to unsigned 8-bit
189    st1       {v4.s}[0], [x2], x5       //store row 1 in destination
190    st1       {v4.s}[1], [x2], x5       //store row 2 in destination
191    st1       {v8.s}[0], [x2], x5       //store row 3 in destination
192    st1       {v8.s}[1], [x2], x5       //store row 4 in destination
193    bgt       loop_4                    //if greater than 0 repeat the loop again
194    b         end_loops
195
196loop_8:                                 //each iteration processes four rows
197
198    ld1       {v4.8b}, [x0], x3         //load row 1 in source 1
199    ld1       {v6.8b}, [x1], x4         //load row 1 in source 2
200    ld1       {v8.8b}, [x0], x3         //load row 2 in source 1
201    ld1       {v10.8b}, [x1], x4        //load row 2 in source 2
202    uxtl      v4.8h, v4.8b              //converting row 1 in source 1 to 16-bit
203    ld1       {v12.8b}, [x0], x3        //load row 3 in source 1
204    ld1       {v14.8b}, [x1], x4        //load row 3 in source 2
205    uxtl      v6.8h, v6.8b              //converting row 1 in source 2 to 16-bit
206    ld1       {v16.8b}, [x0], x3        //load row 4 in source 1
207    ld1       {v18.8b}, [x1], x4        //load row 4 in source 2
208    uxtl      v8.8h, v8.8b              //converting row 2 in source 1 to 16-bit
209    uxtl      v10.8h, v10.8b            //converting row 2 in source 2 to 16-bit
210    mul       v4.8h, v4.8h , v2.h[0]    //weight 1 mult. for row 1
211    mla       v4.8h, v6.8h , v2.h[2]    //weight 2 mult. for row 1
212    uxtl      v12.8h, v12.8b            //converting row 3 in source 1 to 16-bit
213    uxtl      v14.8h, v14.8b            //converting row 3 in source 2 to 16-bit
214    mul       v8.8h, v8.8h , v2.h[0]    //weight 1 mult. for row 2
215    mla       v8.8h, v10.8h , v2.h[2]   //weight 2 mult. for row 2
216    uxtl      v16.8h, v16.8b            //converting row 4 in source 1 to 16-bit
217    uxtl      v18.8h, v18.8b            //converting row 4 in source 2 to 16-bit
218    mul       v12.8h, v12.8h , v2.h[0]  //weight 1 mult. for row 3
219    mla       v12.8h, v14.8h , v2.h[2]  //weight 2 mult. for row 3
220    mul       v16.8h, v16.8h , v2.h[0]  //weight 1 mult. for row 4
221    mla       v16.8h, v18.8h , v2.h[2]  //weight 2 mult. for row 4
222    srshl     v4.8h, v4.8h , v0.8h      //rounds off the weighted samples from row 1
223    srshl     v8.8h, v8.8h , v0.8h      //rounds off the weighted samples from row 2
224    srshl     v12.8h, v12.8h , v0.8h    //rounds off the weighted samples from row 3
225    saddw     v4.8h, v4.8h , v3.8b      //adding offset for row 1
226    srshl     v16.8h, v16.8h , v0.8h    //rounds off the weighted samples from row 4
227    saddw     v8.8h, v8.8h , v3.8b      //adding offset for row 2
228    saddw     v12.8h, v12.8h , v3.8b    //adding offset for row 3
229    sqxtun    v4.8b, v4.8h              //saturating row 1 to unsigned 8-bit
230    saddw     v16.8h, v16.8h , v3.8b    //adding offset for row 4
231    sqxtun    v8.8b, v8.8h              //saturating row 2 to unsigned 8-bit
232    sqxtun    v12.8b, v12.8h            //saturating row 3 to unsigned 8-bit
233    sqxtun    v16.8b, v16.8h            //saturating row 4 to unsigned 8-bit
234    st1       {v4.8b}, [x2], x5         //store row 1 in destination
235    st1       {v8.8b}, [x2], x5         //store row 2 in destination
236    subs      w11, w11, #4              //decrement ht by 4
237    st1       {v12.8b}, [x2], x5        //store row 3 in destination
238    st1       {v16.8b}, [x2], x5        //store row 4 in destination
239    bgt       loop_8                    //if greater than 0 repeat the loop again
240    b         end_loops
241
242loop_16:                                //each iteration processes two rows
243
244    ld1       {v4.8b, v5.8b}, [x0], x3  //load row 1 in source 1
245    ld1       {v6.8b, v7.8b}, [x1], x4  //load row 1 in source 2
246    ld1       {v8.8b, v9.8b}, [x0], x3  //load row 2 in source 1
247    ld1       {v10.8b, v11.8b}, [x1], x4 //load row 2 in source 2
248    uxtl      v20.8h, v4.8b             //converting row 1L in source 1 to 16-bit
249    ld1       {v12.8b, v13.8b}, [x0], x3 //load row 3 in source 1
250    ld1       {v14.8b, v15.8b}, [x1], x4 //load row 3 in source 2
251    uxtl      v22.8h, v6.8b             //converting row 1L in source 2 to 16-bit
252    ld1       {v16.8b, v17.8b}, [x0], x3 //load row 4 in source 1
253    ld1       {v18.8b, v19.8b}, [x1], x4 //load row 4 in source 2
254    uxtl      v4.8h, v5.8b              //converting row 1H in source 1 to 16-bit
255    uxtl      v6.8h, v7.8b              //converting row 1H in source 2 to 16-bit
256    mul       v20.8h, v20.8h , v2.h[0]  //weight 1 mult. for row 1L
257    mla       v20.8h, v22.8h , v2.h[2]  //weight 2 mult. for row 1L
258    uxtl      v24.8h, v8.8b             //converting row 2L in source 1 to 16-bit
259    uxtl      v26.8h, v10.8b            //converting row 2L in source 2 to 16-bit
260    mul       v4.8h, v4.8h , v2.h[0]    //weight 1 mult. for row 1H
261    mla       v4.8h, v6.8h , v2.h[2]    //weight 2 mult. for row 1H
262    uxtl      v8.8h, v9.8b              //converting row 2H in source 1 to 16-bit
263    uxtl      v10.8h, v11.8b            //converting row 2H in source 2 to 16-bit
264    mul       v24.8h, v24.8h , v2.h[0]  //weight 1 mult. for row 2L
265    mla       v24.8h, v26.8h , v2.h[2]  //weight 2 mult. for row 2L
266    uxtl      v28.8h, v12.8b            //converting row 3L in source 1 to 16-bit
267    uxtl      v30.8h, v14.8b            //converting row 3L in source 2 to 16-bit
268    mul       v8.8h, v8.8h , v2.h[0]    //weight 1 mult. for row 2H
269    mla       v8.8h, v10.8h , v2.h[2]   //weight 2 mult. for row 2H
270    uxtl      v12.8h, v13.8b            //converting row 3H in source 1 to 16-bit
271    uxtl      v14.8h, v15.8b            //converting row 3H in source 2 to 16-bit
272    mul       v28.8h, v28.8h , v2.h[0]  //weight 1 mult. for row 3L
273    mla       v28.8h, v30.8h , v2.h[2]  //weight 2 mult. for row 3L
274    uxtl      v22.8h, v16.8b            //converting row 4L in source 1 to 16-bit
275    uxtl      v6.8h, v18.8b             //converting row 4L in source 2 to 16-bit
276    mul       v12.8h, v12.8h , v2.h[0]  //weight 1 mult. for row 3H
277    mla       v12.8h, v14.8h , v2.h[2]  //weight 2 mult. for row 3H
278    uxtl      v16.8h, v17.8b            //converting row 4H in source 1 to 16-bit
279    uxtl      v18.8h, v19.8b            //converting row 4H in source 2 to 16-bit
280    mul       v22.8h, v22.8h , v2.h[0]  //weight 1 mult. for row 4L
281    mla       v22.8h, v6.8h , v2.h[2]   //weight 2 mult. for row 4L
282    srshl     v20.8h, v20.8h , v0.8h    //rounds off the weighted samples from row 1L
283    mul       v16.8h, v16.8h , v2.h[0]  //weight 1 mult. for row 4H
284    mla       v16.8h, v18.8h , v2.h[2]  //weight 2 mult. for row 4H
285    srshl     v4.8h, v4.8h , v0.8h      //rounds off the weighted samples from row 1H
286    srshl     v24.8h, v24.8h , v0.8h    //rounds off the weighted samples from row 2L
287    saddw     v20.8h, v20.8h , v3.8b    //adding offset for row 1L
288    srshl     v8.8h, v8.8h , v0.8h      //rounds off the weighted samples from row 2H
289    saddw     v4.8h, v4.8h , v3.8b      //adding offset for row 1H
290    srshl     v28.8h, v28.8h , v0.8h    //rounds off the weighted samples from row 3L
291    saddw     v24.8h, v24.8h , v3.8b    //adding offset for row 2L
292    srshl     v12.8h, v12.8h , v0.8h    //rounds off the weighted samples from row 3H
293    saddw     v8.8h, v8.8h , v3.8b      //adding offset for row 2H
294    srshl     v22.8h, v22.8h , v0.8h    //rounds off the weighted samples from row 4L
295    saddw     v28.8h, v28.8h , v3.8b    //adding offset for row 3L
296    srshl     v16.8h, v16.8h , v0.8h    //rounds off the weighted samples from row 4H
297    saddw     v12.8h, v12.8h , v3.8b    //adding offset for row 3H
298    sqxtun    v26.8b, v20.8h            //saturating row 1L to unsigned 8-bit
299    saddw     v22.8h, v22.8h , v3.8b    //adding offset for row 4L
300    sqxtun    v27.8b, v4.8h             //saturating row 1H to unsigned 8-bit
301    saddw     v16.8h, v16.8h , v3.8b    //adding offset for row 4H
302    sqxtun    v10.8b, v24.8h            //saturating row 2L to unsigned 8-bit
303    sqxtun    v11.8b, v8.8h             //saturating row 2H to unsigned 8-bit
304    sqxtun    v30.8b, v28.8h            //saturating row 3L to unsigned 8-bit
305    sqxtun    v31.8b, v12.8h            //saturating row 3H to unsigned 8-bit
306    st1       {v26.8b, v27.8b}, [x2], x5 //store row 1 in destination
307    sqxtun    v14.8b, v22.8h            //saturating row 4L to unsigned 8-bit
308    sqxtun    v15.8b, v16.8h            //saturating row 4H to unsigned 8-bit
309    st1       {v10.8b, v11.8b}, [x2], x5 //store row 2 in destination
310    subs      w11, w11, #4              //decrement ht by 4
311    st1       {v30.8b, v31.8b}, [x2], x5 //store row 3 in destination
312    st1       {v14.8b, v15.8b}, [x2], x5 //store row 4 in destination
313    bgt       loop_16                   //if greater than 0 repeat the loop again
314
315end_loops:
316
317    // LDMFD sp!,{x4-x12,x15}                //Reload the registers from sp
318    ldp       x19, x20, [sp], #16
319    pop_v_regs
320    ret
321
322
323//*******************************************************************************
324//* @function
325//*  ih264_weighted_bi_pred_chroma_av8()
326//*
327//* @brief
328//*  This routine performs the default weighted prediction as described in sec
329//* 8.4.2.3.2 titled "Weighted sample prediction process" for chroma.
330//*
331//* @par Description:
332//*  This function gets two ht x wd blocks, calculates the weighted samples,
333//* rounds off, adds offset and stores it in the destination block for U and V.
334//*
335//* @param[in] puc_src1
336//*  UWORD8 Pointer to the buffer containing the input block 1.
337//*
338//* @param[in] puc_src2
339//*  UWORD8 Pointer to the buffer containing the input block 2.
340//*
341//* @param[out] puc_dst
342//*  UWORD8 pointer to the destination where the output block is stored.
343//*
344//* @param[in] src_strd1
345//*  Stride of the input buffer 1
346//*
347//* @param[in] src_strd2
348//*  Stride of the input buffer 2
349//*
350//* @param[in] dst_strd
351//*  Stride of the destination buffer
352//*
353//* @param[in] log_WD
354//*  number of bits to be rounded off
355//*
356//* @param[in] wt1
357//*  weights for the weighted prediction in U and V
358//*
359//* @param[in] wt2
360//*  weights for the weighted prediction in U and V
361//*
362//* @param[in] ofst1
363//*  offset 1 used after rounding off for U an dV
364//*
365//* @param[in] ofst2
366//*  offset 2 used after rounding off for U and V
367//*
368//* @param[in] ht
369//*  integer height of the array
370//*
371//* @param[in] wd
372//*  integer width of the array
373//*
374//* @returns
375//*  None
376//*
377//* @remarks
378//*  (ht,wd) can be (2,2), (2,4), (4,2), (4,4), (4,8), (8,4) or (8,8).
379//*
380//*******************************************************************************
381//*/
382//void ih264_weighted_bi_pred_chroma_av8(UWORD8 *puc_src1,
383//                                       UWORD8 *puc_src2,
384//                                       UWORD8 *puc_dst,
385//                                       WORD32 src_strd1,
386//                                       WORD32 src_strd2,
387//                                       WORD32 dst_strd,
388//                                       WORD32 log_WD,
389//                                       WORD32 wt1,
390//                                       WORD32 wt2,
391//                                       WORD32 ofst1,
392//                                       WORD32 ofst2,
393//                                       WORD32 ht,
394//                                       WORD32 wd)
395//
396//**************Variables Vs Registers*****************************************
397//    x0      => puc_src1
398//    x1      => puc_src2
399//    x2      => puc_dst
400//    w3      => src_strd1
401//    w4      => src_strd2
402//    w5      => dst_strd
403//    w6      => log_WD
404//    w7      => wt1
405//    [sp]    => wt2       (w8)
406//    [sp+8]  => ofst1     (w9)
407//    [sp+16] => ofst2     (w10)
408//    [sp+24] => ht        (w11)
409//    [sp+32] => wd        (w12)
410//
411
412
413
414
415
416    .global ih264_weighted_bi_pred_chroma_av8
417
418ih264_weighted_bi_pred_chroma_av8:
419
420    // STMFD sp!, {x4-x12,x14}                //stack stores the values of the arguments
421    push_v_regs
422    sxtw      x3, w3
423    sxtw      x4, w4
424    sxtw      x5, w5
425    stp       x19, x20, [sp, #-16]!
426
427
428    ldr       w8, [sp, #80]             //Load wt2 in w8
429    dup       v4.4s, w8                 //Q2 = (wt2_u, wt2_v) (32-bit)
430    dup       v2.4s, w7                 //Q1 = (wt1_u, wt1_v) (32-bit)
431    add       w6, w6, #1                //w6  = log_WD + 1
432    ldr       w9, [sp, #88]             //Load ofst1 in w9
433    ldr       w10, [sp, #96]            //Load ofst2 in w10
434    neg       w20, w6                   //w20 = -(log_WD + 1)
435    dup       v0.8h, w20                //Q0  = -(log_WD + 1) (16-bit)
436    ldr       w11, [sp, #104]           //Load ht in x11
437    ldr       w12, [sp, #112]           //Load wd in x12
438    dup       v20.8h, w9                //0ffset1
439    dup       v21.8h, w10               //0ffset2
440    srhadd    v6.8b, v20.8b, v21.8b
441    sxtl      v6.8h, v6.8b
442    cmp       w12, #8                   //check if wd is 8
443    beq       loop_8_uv                 //branch if wd is 8
444    cmp       w12, #4                   //check if wd is 4
445    beq       loop_4_uv                 //branch if wd is 4
446
447loop_2_uv:                              //each iteration processes two rows
448
449    ld1       {v8.s}[0], [x0], x3       //load row 1 in source 1
450    ld1       {v8.s}[1], [x0], x3       //load row 2 in source 1
451    ld1       {v10.s}[0], [x1], x4      //load row 1 in source 2
452    ld1       {v10.s}[1], [x1], x4      //load row 2 in source 2
453    uxtl      v8.8h, v8.8b              //converting rows 1,2 in source 1 to 16-bit
454    uxtl      v10.8h, v10.8b            //converting rows 1,2 in source 2 to 16-bit
455    mul       v8.8h, v8.8h , v2.8h      //weight 1 mult. for rows 1,2
456    mla       v8.8h, v10.8h , v4.8h     //weight 2 mult. for rows 1,2
457    srshl     v8.8h, v8.8h , v0.8h      //rounds off the weighted samples from rows 1,2
458    add       v8.8h, v8.8h , v6.8h      //adding offset for rows 1,2
459    sqxtun    v8.8b, v8.8h              //saturating rows 1,2 to unsigned 8-bit/
460    st1       {v8.s}[0], [x2], x5       //store row 1 in destination
461    st1       {v8.s}[1], [x2], x5       //store row 2 in destination
462    subs      w11, w11, #2              //decrement ht by 2
463    bgt       loop_2_uv                 //if greater than 0 repeat the loop again
464    b         end_loops_uv
465
466loop_4_uv:                              //each iteration processes two rows
467
468    ld1       {v8.8b}, [x0], x3         //load row 1 in source 1
469    ld1       {v10.8b}, [x1], x4        //load row 1 in source 2
470    uxtl      v8.8h, v8.8b              //converting row 1 in source 1 to 16-bit
471    ld1       {v12.8b}, [x0], x3        //load row 2 in source 1
472    uxtl      v10.8h, v10.8b            //converting row 1 in source 2 to 16-bit
473    ld1       {v14.8b}, [x1], x4        //load row 2 in source 2
474    uxtl      v12.8h, v12.8b            //converting row 2 in source 1 to 16-bit
475    mul       v8.8h, v8.8h , v2.8h      //weight 1 mult. for row 1
476    mla       v8.8h, v10.8h , v4.8h     //weight 2 mult. for row 1
477    uxtl      v14.8h, v14.8b            //converting row 2 in source 2 to 16-bit
478    mul       v12.8h, v12.8h , v2.8h    //weight 1 mult. for row 2
479    mla       v12.8h, v14.8h , v4.8h    //weight 2 mult. for row 2
480    subs      w11, w11, #2              //decrement ht by 2
481    srshl     v8.8h, v8.8h , v0.8h      //rounds off the weighted samples from row 1
482    srshl     v12.8h, v12.8h , v0.8h    //rounds off the weighted samples from row 2
483    add       v8.8h, v8.8h , v6.8h      //adding offset for row 1
484    add       v12.8h, v12.8h , v6.8h    //adding offset for row 2
485    sqxtun    v8.8b, v8.8h              //saturating row 1 to unsigned 8-bit
486    sqxtun    v12.8b, v12.8h            //saturating row 2 to unsigned 8-bit
487    st1       {v8.8b}, [x2], x5         //store row 1 in destination
488    st1       {v12.8b}, [x2], x5        //store row 2 in destination
489    bgt       loop_4_uv                 //if greater than 0 repeat the loop again
490    b         end_loops_uv
491
492loop_8_uv:                              //each iteration processes two rows
493
494    ld1       {v8.8b, v9.8b}, [x0], x3  //load row 1 in source 1
495    ld1       {v10.8b, v11.8b}, [x1], x4 //load row 1 in source 2
496    ld1       {v12.8b, v13.8b}, [x0], x3 //load row 2 in source 1
497    ld1       {v14.8b, v15.8b}, [x1], x4 //load row 2 in source 2
498    uxtl      v24.8h, v8.8b             //converting row 1L in source 1 to 16-bit
499    ld1       {v16.8b, v17.8b}, [x0], x3 //load row 3 in source 1
500    ld1       {v18.8b, v19.8b}, [x1], x4 //load row 3 in source 2
501    uxtl      v26.8h, v10.8b            //converting row 1L in source 2 to 16-bit
502    ld1       {v20.8b, v21.8b}, [x0], x3 //load row 4 in source 1
503    ld1       {v22.8b, v23.8b}, [x1], x4 //load row 4 in source 2
504    uxtl      v8.8h, v9.8b              //converting row 1H in source 1 to 16-bit
505    uxtl      v10.8h, v11.8b            //converting row 1H in source 2 to 16-bit
506    mul       v24.8h, v24.8h , v2.8h    //weight 1 mult. for row 1L
507    mla       v24.8h, v26.8h , v4.8h    //weight 2 mult. for row 1L
508    uxtl      v28.8h, v12.8b            //converting row 2L in source 1 to 16-bit
509    uxtl      v30.8h, v14.8b            //converting row 2L in source 2 to 16-bit
510    mul       v8.8h, v8.8h , v2.8h      //weight 1 mult. for row 1H
511    mla       v8.8h, v10.8h , v4.8h     //weight 2 mult. for row 1H
512    uxtl      v12.8h, v13.8b            //converting row 2H in source 1 to 16-bit
513    uxtl      v14.8h, v15.8b            //converting row 2H in source 2 to 16-bit
514    mul       v28.8h, v28.8h , v2.8h    //weight 1 mult. for row 2L
515    mla       v28.8h, v30.8h , v4.8h    //weight 2 mult. for row 2L
516    uxtl      v26.8h, v16.8b            //converting row 3L in source 1 to 16-bit
517    uxtl      v10.8h, v18.8b            //converting row 3L in source 2 to 16-bit
518    mul       v12.8h, v12.8h , v2.8h    //weight 1 mult. for row 2H
519    mla       v12.8h, v14.8h , v4.8h    //weight 2 mult. for row 2H
520    uxtl      v16.8h, v17.8b            //converting row 3H in source 1 to 16-bit
521    uxtl      v18.8h, v19.8b            //converting row 3H in source 2 to 16-bit
522    mul       v26.8h, v26.8h , v2.8h    //weight 1 mult. for row 3L
523    mla       v26.8h, v10.8h , v4.8h    //weight 2 mult. for row 3L
524    uxtl      v30.8h, v20.8b            //converting row 4L in source 1 to 16-bit
525    uxtl      v14.8h, v22.8b            //converting row 4L in source 2 to 16-bit
526    mul       v16.8h, v16.8h , v2.8h    //weight 1 mult. for row 3H
527    mla       v16.8h, v18.8h , v4.8h    //weight 2 mult. for row 3H
528    uxtl      v20.8h, v21.8b            //converting row 4H in source 1 to 16-bit
529    uxtl      v22.8h, v23.8b            //converting row 4H in source 2 to 16-bit
530    mul       v30.8h, v30.8h , v2.8h    //weight 1 mult. for row 4L
531    mla       v30.8h, v14.8h , v4.8h    //weight 2 mult. for row 4L
532    srshl     v24.8h, v24.8h , v0.8h    //rounds off the weighted samples from row 1L
533    mul       v20.8h, v20.8h , v2.8h    //weight 1 mult. for row 4H
534    mla       v20.8h, v22.8h , v4.8h    //weight 2 mult. for row 4H
535    srshl     v8.8h, v8.8h , v0.8h      //rounds off the weighted samples from row 1H
536    srshl     v28.8h, v28.8h , v0.8h    //rounds off the weighted samples from row 2L
537    add       v24.8h, v24.8h , v6.8h    //adding offset for row 1L
538    srshl     v12.8h, v12.8h , v0.8h    //rounds off the weighted samples from row 2H
539    add       v8.8h, v8.8h , v6.8h      //adding offset for row 1H
540    srshl     v26.8h, v26.8h , v0.8h    //rounds off the weighted samples from row 3L
541    add       v28.8h, v28.8h , v6.8h    //adding offset for row 2L
542    srshl     v16.8h, v16.8h , v0.8h    //rounds off the weighted samples from row 3H
543    add       v12.8h, v12.8h , v6.8h    //adding offset for row 2H
544    srshl     v30.8h, v30.8h , v0.8h    //rounds off the weighted samples from row 4L
545    add       v26.8h, v26.8h , v6.8h    //adding offset for row 3L
546    srshl     v20.8h, v20.8h , v0.8h    //rounds off the weighted samples from row 4H
547    add       v16.8h, v16.8h , v6.8h    //adding offset for row 3H
548    sqxtun    v10.8b, v24.8h            //saturating row 1L to unsigned 8-bit
549    add       v30.8h, v30.8h , v6.8h    //adding offset for row 4L
550    sqxtun    v11.8b, v8.8h             //saturating row 1H to unsigned 8-bit
551    add       v20.8h, v20.8h , v6.8h    //adding offset for row 4H
552    sqxtun    v18.8b, v28.8h            //saturating row 2L to unsigned 8-bit
553    sqxtun    v19.8b, v12.8h            //saturating row 2H to unsigned 8-bit
554    sqxtun    v14.8b, v26.8h            //saturating row 3L to unsigned 8-bit
555    sqxtun    v15.8b, v16.8h            //saturating row 3H to unsigned 8-bit
556    st1       {v10.8b, v11.8b}, [x2], x5 //store row 1 in destination
557    sqxtun    v22.8b, v30.8h            //saturating row 4L to unsigned 8-bit
558    sqxtun    v23.8b, v20.8h            //saturating row 4H to unsigned 8-bit
559    st1       {v18.8b, v19.8b}, [x2], x5 //store row 2 in destination
560    subs      w11, w11, #4              //decrement ht by 4
561    st1       {v14.8b, v15.8b}, [x2], x5 //store row 3 in destination
562    st1       {v22.8b, v23.8b}, [x2], x5 //store row 4 in destination
563    bgt       loop_8_uv                 //if greater than 0 repeat the loop again
564
565end_loops_uv:
566
567    // LDMFD sp!,{x4-x12,x15}                //Reload the registers from sp
568    ldp       x19, x20, [sp], #16
569    pop_v_regs
570    ret
571
572
573
574