1///*****************************************************************************
2//*
3//* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
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///**
19//*******************************************************************************
20//* @file
21//*  ihevc_weighted_pred_uni.s
22//*
23//* @brief
24//*  contains function definitions for weighted prediction used in inter
25//* prediction
26//*
27//* @author
28//*  parthiban v
29//*
30//* @par list of functions:
31//*  - ihevc_weighted_pred_uni()
32//*
33//* @remarks
34//*  none
35//*
36//*******************************************************************************
37//*/
38
39///**
40//*******************************************************************************
41//*
42//* @brief
43//*  does uni-weighted prediction on the array pointed by  pi2_src and stores
44//* it at the location pointed by pi2_dst assumptions : the function is
45//* optimized considering the fact width and  height are multiple of 2.
46//*
47//* @par description:
48//*  dst = ( (src + lvl_shift) * wgt0 + (1 << (shift - 1)) )  >> shift +
49//* offset
50//*
51//* @param[in] pi2_src
52//*  pointer to the source
53//*
54//* @param[out] pu1_dst
55//*  pointer to the destination
56//*
57//* @param[in] src_strd
58//*  source stride
59//*
60//* @param[in] dst_strd
61//*  destination stride
62//*
63//* @param[in] wgt0
64//*  weight to be multiplied to the source
65//*
66//* @param[in] off0
67//*  offset to be added after rounding and
68//*
69//* @param[in] shifting
70//*
71//*
72//* @param[in] shift
73//*  (14 bit depth) + log2_weight_denominator
74//*
75//* @param[in] lvl_shift
76//*  added before shift and offset
77//*
78//* @param[in] ht
79//*  height of the source
80//*
81//* @param[in] wd
82//*  width of the source
83//*
84//* @returns
85//*
86//* @remarks
87//*  none
88//*
89//*******************************************************************************
90//*/
91
92//void ihevc_weighted_pred_uni(word16 *pi2_src,
93//                             uword8 *pu1_dst,
94//                             word32 src_strd,
95//                             word32 dst_strd,
96//                             word32 wgt0,
97//                             word32 off0,
98//                             word32 shift,
99//                             word32 lvl_shift,
100//                             word32 ht,
101//                             word32 wd)
102
103//**************variables vs registers*****************************************
104//    x0 => *pi2_src
105//    x1 => *pu1_dst
106//    x2 =>  src_strd
107//    x3 =>  dst_strd
108//    x4 =>  wgt0
109//    x5 =>  off0
110//    x6 =>  shift
111//    x7 =>  lvl_shift
112//    x8 =>    ht
113//    x9    =>    wd
114
115.text
116.align 4
117
118.include "ihevc_neon_macros.s"
119
120.globl ihevc_weighted_pred_uni_av8
121
122.type ihevc_weighted_pred_uni_av8, %function
123
124ihevc_weighted_pred_uni_av8:
125
126    // stmfd sp!, {x4-x12, x14}            //stack stores the values of the arguments
127
128    ldr         w8,[sp,#0]
129    ldr         w9,[sp,#8]
130
131    // stmfd sp!, {x4-x12, x14}                //stack stores the values of the arguments
132
133    stp         x19, x20,[sp,#-16]!
134    stp         x21, x22,[sp,#-16]!
135
136    mov         x15,x4 // src_strd2 40
137    mov         x16,x5 // dst_strd 44
138    mov         x17,x6 // lvl_shift1 48
139    mov         x19,x7 // lvl_shift2 52
140    mov         x20,x8 // ht 56
141    mov         x21,x9 // wd 60
142
143    mov         x4,x15                      //load wgt0
144    mov         x7,x19                      //load lvl_shift
145    mov         x11,#1
146    mov         x5,x16                      //load off0
147    mul         x10, x7, x4                 //lvl_shift * wgt0
148    mov         x6,x17                      //load shift
149    mov         x8,x20                      //load ht
150    lsl         x22,x5,x6
151    add         x10,x10,x22                 //lvl_shift * wgt0 + (off0 << shift)
152    mov         x9,x21                      //load wt
153    sub         x12,x6,#1
154    mov         v0.4h[0], w4                //moved for scalar multiplication
155    lsl         x2,x2,#1
156    dup         v28.4s,w6                   //vmovq_n_s32(tmp_shift)
157    lsl         x22,x11,x12
158    add         x10,x10,x22                 //tmp_lvl_shift += (1 << (shift - 1))
159    dup         v30.4s,w10                  //vmovq_n_s32(tmp_lvl_shift)
160    neg         v28.4s, v28.4s
161    lsl         x4,x9,#1
162
163    cmp         x8,#0                       //check ht == 0
164    beq         end_loops                   //if equal, then end the function
165
166outer_loop:
167    cmp         x9,#0                       //check wd == 0
168    beq         end_loops                   //if equal, then end the function
169
170core_loop:
171    add         x5,x0,x2                    //pi2_src_tmp1 = pi2_src1 + 2*src_strd1(2* because pi1_src is a 16 bit pointer)
172    add         x6,x1,x3                    //pu1_dst_tmp = pu1_dst + dst_strd
173    ld1         {v1.4h},[x0],#8             //load and increment the pi2_src
174    ld1         {v2.4h},[x5],x2             //load and increment the pi2_src_tmp ii iteration
175    smull       v4.4s, v1.4h, v0.4h[0]      //vmull_n_s16(pi2_src_val1, (int16_t) wgt0)
176
177    add         v4.4s,  v4.4s ,  v30.4s     //vaddq_s32(i4_tmp1_t, tmp_lvl_shift_t)
178    ld1         {v3.4h},[x5],x2             //load and increment the pi2_src iii iteration
179
180    smull       v6.4s, v2.4h, v0.4h[0]      //vmull_n_s16(pi2_src_val2, (int16_t) wgt0) ii iteration
181    ld1         {v5.4h},[x5],x2             //load and increment the pi2_src_tmp iv iteration
182
183    sshl        v4.4s,v4.4s,v28.4s
184    //vshl.s32    q2,q2,q14                    //vshlq_s32(i4_tmp1_t, tmp_shift_t)
185    add         v6.4s,  v6.4s ,  v30.4s     //vaddq_s32(i4_tmp2_t, tmp_lvl_shift_t) ii iteration
186
187    smull       v7.4s, v3.4h, v0.4h[0]      //vmull_n_s16(pi2_src_val1, (int16_t) wgt0) iii iteration
188    sqxtun      v4.4h, v4.4s                //vqmovun_s32(sto_res_tmp1)
189
190    add         v7.4s,  v7.4s ,  v30.4s     //vaddq_s32(i4_tmp1_t, tmp_lvl_shift_t) iii iteration
191    //mov v5, v4                        //vcombine_u16(sto_res_tmp2, sto_res_tmp2)
192
193    sshl        v6.4s,v6.4s,v28.4s
194    //vshl.s32    q3,q3,q14                    //vshlq_s32(i4_tmp2_t, tmp_shift_t) ii iteration
195
196    smull       v16.4s, v5.4h, v0.4h[0]     //vmull_n_s16(pi2_src_val2, (int16_t) wgt0) iv iteration
197    uqxtn       v4.8b,  v4.8h               //vqmovn_u16(sto_res_tmp3)
198
199    sshl        v7.4s,v7.4s,v28.4s
200    //vshl.s32    q5,q5,q14                    //vshlq_s32(i4_tmp1_t, tmp_shift_t) iii iteration
201    sqxtun      v6.4h, v6.4s                //vqmovun_s32(sto_res_tmp1) ii iteration
202
203    add         v16.4s,  v16.4s ,  v30.4s   //vaddq_s32(i4_tmp2_t, tmp_lvl_shift_t) iv iteration
204    //mov v7, v6                        //vcombine_u16(sto_res_tmp2, sto_res_tmp2) ii iteration
205
206    sqxtun      v7.4h, v7.4s                //vqmovun_s32(sto_res_tmp1) iii iteration
207
208    sshl        v16.4s,v16.4s,v28.4s
209    //vshl.s32    q6,q6,q14                    //vshlq_s32(i4_tmp2_t, tmp_shift_t) iv iteration
210    st1         {v4.s}[0],[x1],#4           //store pu1_dst i iteration
211    //mov v11, v10                        //vcombine_u16(sto_res_tmp2, sto_res_tmp2) iii iteration
212
213    uqxtn       v6.8b,  v6.8h               //vqmovn_u16(sto_res_tmp3) ii iteration
214    st1         {v6.s}[0],[x6],x3           //store pu1_dst ii iteration
215
216    uqxtn       v7.8b,  v7.8h               //vqmovn_u16(sto_res_tmp3) iii iteration
217    sqxtun      v16.4h, v16.4s              //vqmovun_s32(sto_res_tmp1) iv iteration
218
219    //mov v13, v12                        //vcombine_u16(sto_res_tmp2, sto_res_tmp2) iv iteration
220    st1         {v7.s}[0],[x6],x3           //store pu1_dst i iteration iii iteration
221    uqxtn       v16.8b,  v16.8h             //vqmovn_u16(sto_res_tmp3) iv iteration
222
223    subs        x9,x9,#4                    //decrement wd by 4 and check for 0
224    st1         {v16.s}[0],[x6],x3          //store pu1_dst iv iteration
225    bgt         core_loop                   //if greater than 0 repeat the core loop again
226
227end_core_loop:
228    sub         x22,x4,x2,lsl #2            //2*src_strd - wd
229    neg         x11, x22
230    subs        x8,x8,#4                    //decrement the ht by 4
231    add         x0,x0,x11                   //pi2_src + 4*src_strd - 2*wd(since pi2_src is 16 bit pointer double the increment with double the wd decrement)
232    asr         x9,x4,#1
233    sub         x22,x9,x3,lsl #2            //2*dst_strd - wd
234    neg         x12, x22
235    add         x1,x1,x12                   //pu1_dst + dst_std - wd
236    bgt         core_loop                   //if ht is greater than 0 goto outer_loop
237
238end_loops:
239    // ldmfd sp!,{x4-x12,x15}                  //reload the registers from sp
240    ldp         x21, x22,[sp],#16
241    ldp         x19, x20,[sp],#16
242
243    ret
244
245
246