1 /*****************************************************************************
2 * ppccommon.h: h264 encoder
3 *****************************************************************************
4 * Copyright (C) 2003 Laurent Aimar
5 * $Id: ppccommon.h,v 1.1 2004/06/03 19:27:07 fenrir Exp $
7 * Authors: Eric Petit <titer@m0k.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /***********************************************************************
25 * For constant vectors, use parentheses on OS X and braces on Linux
26 **********************************************************************/
33 /***********************************************************************
35 **********************************************************************/
36 #define vec_u8_t vector unsigned char
37 #define vec_s8_t vector signed char
38 #define vec_u16_t vector unsigned short
39 #define vec_s16_t vector signed short
40 #define vec_u32_t vector unsigned int
41 #define vec_s32_t vector signed int
45 vector unsigned int v;
50 vector unsigned short v;
53 /***********************************************************************
55 **********************************************************************/
56 #define LOAD_ZERO const vec_u8_t zerov = vec_splat_u8( 0 )
58 #define zero_u8v (vec_u8_t) zerov
59 #define zero_s8v (vec_s8_t) zerov
60 #define zero_u16v (vec_u16_t) zerov
61 #define zero_s16v (vec_s16_t) zerov
62 #define zero_u32v (vec_u32_t) zerov
63 #define zero_s32v (vec_s32_t) zerov
65 /***********************************************************************
66 * 8 <-> 16 bits conversions
67 **********************************************************************/
68 #define vec_u8_to_u16_h(v) (vec_u16_t) vec_mergeh( zero_u8v, (vec_u8_t) v )
69 #define vec_u8_to_u16_l(v) (vec_u16_t) vec_mergel( zero_u8v, (vec_u8_t) v )
70 #define vec_u8_to_s16_h(v) (vec_s16_t) vec_mergeh( zero_u8v, (vec_u8_t) v )
71 #define vec_u8_to_s16_l(v) (vec_s16_t) vec_mergel( zero_u8v, (vec_u8_t) v )
73 #define vec_u8_to_u16(v) vec_u8_to_u16_h(v)
74 #define vec_u8_to_s16(v) vec_u8_to_s16_h(v)
76 #define vec_u16_to_u8(v) vec_pack( v, zero_u16v )
77 #define vec_s16_to_u8(v) vec_packsu( v, zero_s16v )
79 /***********************************************************************
80 * PREP_LOAD: declares two vectors required to perform unaligned loads
81 * VEC_LOAD: loads n bytes from u8 * p into vector v of type t
82 **********************************************************************/
86 #define VEC_LOAD( p, v, n, t ) \
87 _hv = vec_ld( 0, p ); \
88 v = (t) vec_lvsl( 0, p ); \
89 _lv = vec_ld( n - 1, p ); \
90 v = (t) vec_perm( _hv, _lv, (vec_u8_t) v )
92 /***********************************************************************
93 * PREP_STORE##n: declares required vectors to store n bytes to a
94 * potentially unaligned address
95 * VEC_STORE##n: stores n bytes from vector v to address p
96 **********************************************************************/
97 #define PREP_STORE16 \
98 vec_u8_t _tmp1v, _tmp2v \
100 #define VEC_STORE16( v, p ) \
101 _hv = vec_ld( 0, p ); \
102 _tmp2v = vec_lvsl( 0, p ); \
103 _lv = vec_ld( 15, p ); \
104 _tmp1v = vec_perm( _lv, _hv, _tmp2v ); \
105 _tmp2v = vec_lvsr( 0, p ); \
106 _lv = vec_perm( (vec_u8_t) v, _tmp1v, _tmp2v ); \
107 vec_st( _lv, 15, (uint8_t *) p ); \
108 _hv = vec_perm( _tmp1v, (vec_u8_t) v, _tmp2v ); \
109 vec_st( _hv, 0, (uint8_t *) p )
111 #define PREP_STORE8 \
113 vec_u8_t _tmp3v, _tmp4v; \
114 const vec_u8_t sel_h = \
115 (vec_u8_t) CV(-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0)
117 #define PREP_STORE8_HL \
119 const vec_u8_t sel_l = \
120 (vec_u8_t) CV(0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1)
122 #define VEC_STORE8 VEC_STORE8_H
124 #define VEC_STORE8_H( v, p ) \
125 _tmp3v = vec_lvsr( 0, (uint8_t *) p ); \
126 _tmp4v = vec_perm( (vec_u8_t) v, (vec_u8_t) v, _tmp3v ); \
127 _lv = vec_ld( 7, (uint8_t *) p ); \
128 _tmp1v = vec_perm( sel_h, zero_u8v, _tmp3v ); \
129 _lv = vec_sel( _lv, _tmp4v, _tmp1v ); \
130 vec_st( _lv, 7, (uint8_t *) p ); \
131 _hv = vec_ld( 0, (uint8_t *) p ); \
132 _tmp2v = vec_perm( zero_u8v, sel_h, _tmp3v ); \
133 _hv = vec_sel( _hv, _tmp4v, _tmp2v ); \
134 vec_st( _hv, 0, (uint8_t *) p )
136 #define VEC_STORE8_L( v, p ) \
137 _tmp3v = vec_lvsr( 8, (uint8_t *) p ); \
138 _tmp4v = vec_perm( (vec_u8_t) v, (vec_u8_t) v, _tmp3v ); \
139 _lv = vec_ld( 7, (uint8_t *) p ); \
140 _tmp1v = vec_perm( sel_l, zero_u8v, _tmp3v ); \
141 _lv = vec_sel( _lv, _tmp4v, _tmp1v ); \
142 vec_st( _lv, 7, (uint8_t *) p ); \
143 _hv = vec_ld( 0, (uint8_t *) p ); \
144 _tmp2v = vec_perm( zero_u8v, sel_l, _tmp3v ); \
145 _hv = vec_sel( _hv, _tmp4v, _tmp2v ); \
146 vec_st( _hv, 0, (uint8_t *) p )
148 #define PREP_STORE4 \
151 const vec_u8_t sel = \
152 (vec_u8_t) CV(-1,-1,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0)
154 #define VEC_STORE4( v, p ) \
155 _tmp3v = vec_lvsr( 0, p ); \
156 v = vec_perm( v, v, _tmp3v ); \
157 _lv = vec_ld( 3, p ); \
158 _tmp1v = vec_perm( sel, zero_u8v, _tmp3v ); \
159 _lv = vec_sel( _lv, v, _tmp1v ); \
160 vec_st( _lv, 3, p ); \
161 _hv = vec_ld( 0, p ); \
162 _tmp2v = vec_perm( zero_u8v, sel, _tmp3v ); \
163 _hv = vec_sel( _hv, v, _tmp2v ); \
166 /***********************************************************************
168 ***********************************************************************
169 * Transposes a 8x8 matrix of s16 vectors
170 **********************************************************************/
171 #define VEC_TRANSPOSE_8(a0,a1,a2,a3,a4,a5,a6,a7,b0,b1,b2,b3,b4,b5,b6,b7) \
172 b0 = vec_mergeh( a0, a4 ); \
173 b1 = vec_mergel( a0, a4 ); \
174 b2 = vec_mergeh( a1, a5 ); \
175 b3 = vec_mergel( a1, a5 ); \
176 b4 = vec_mergeh( a2, a6 ); \
177 b5 = vec_mergel( a2, a6 ); \
178 b6 = vec_mergeh( a3, a7 ); \
179 b7 = vec_mergel( a3, a7 ); \
180 a0 = vec_mergeh( b0, b4 ); \
181 a1 = vec_mergel( b0, b4 ); \
182 a2 = vec_mergeh( b1, b5 ); \
183 a3 = vec_mergel( b1, b5 ); \
184 a4 = vec_mergeh( b2, b6 ); \
185 a5 = vec_mergel( b2, b6 ); \
186 a6 = vec_mergeh( b3, b7 ); \
187 a7 = vec_mergel( b3, b7 ); \
188 b0 = vec_mergeh( a0, a4 ); \
189 b1 = vec_mergel( a0, a4 ); \
190 b2 = vec_mergeh( a1, a5 ); \
191 b3 = vec_mergel( a1, a5 ); \
192 b4 = vec_mergeh( a2, a6 ); \
193 b5 = vec_mergel( a2, a6 ); \
194 b6 = vec_mergeh( a3, a7 ); \
195 b7 = vec_mergel( a3, a7 )
197 /***********************************************************************
199 ***********************************************************************
200 * Transposes a 4x4 matrix of s16 vectors.
201 * Actually source and destination are 8x4. The low elements of the
202 * source are discarded and the low elements of the destination mustn't
204 **********************************************************************/
205 #define VEC_TRANSPOSE_4(a0,a1,a2,a3,b0,b1,b2,b3) \
206 b0 = vec_mergeh( a0, a0 ); \
207 b1 = vec_mergeh( a1, a0 ); \
208 b2 = vec_mergeh( a2, a0 ); \
209 b3 = vec_mergeh( a3, a0 ); \
210 a0 = vec_mergeh( b0, b2 ); \
211 a1 = vec_mergel( b0, b2 ); \
212 a2 = vec_mergeh( b1, b3 ); \
213 a3 = vec_mergel( b1, b3 ); \
214 b0 = vec_mergeh( a0, a2 ); \
215 b1 = vec_mergel( a0, a2 ); \
216 b2 = vec_mergeh( a1, a3 ); \
217 b3 = vec_mergel( a1, a3 )
219 /***********************************************************************
221 ***********************************************************************
226 * Loads n bytes from p1 and p2, do the diff of the high elements into
227 * d, increments p1 and p2 by i1 and i2
228 **********************************************************************/
232 vec_s16_t pix1v, pix2v;
234 #define VEC_DIFF_H(p1,i1,p2,i2,n,d) \
235 VEC_LOAD( p1, pix1v, n, vec_s16_t ); \
236 pix1v = vec_u8_to_s16( pix1v ); \
237 VEC_LOAD( p2, pix2v, n, vec_s16_t ); \
238 pix2v = vec_u8_to_s16( pix2v ); \
239 d = vec_sub( pix1v, pix2v ); \
243 /***********************************************************************
245 ***********************************************************************
250 * Loads 16 bytes from p1 and p2, do the diff of the high elements into
251 * dh, the diff of the low elements into dl, increments p1 and p2 by i1
253 **********************************************************************/
254 #define VEC_DIFF_HL(p1,i1,p2,i2,dh,dl) \
255 VEC_LOAD( p1, pix1v, 16, vec_s16_t ); \
256 temp0v = vec_u8_to_s16_h( pix1v ); \
257 temp1v = vec_u8_to_s16_l( pix1v ); \
258 VEC_LOAD( p2, pix2v, 16, vec_s16_t ); \
259 temp2v = vec_u8_to_s16_h( pix2v ); \
260 temp3v = vec_u8_to_s16_l( pix2v ); \
261 dh = vec_sub( temp0v, temp2v ); \
262 dl = vec_sub( temp1v, temp3v ); \
266 /***********************************************************************
267 * VEC_DIFF_H_8BYTE_ALIGNED
268 ***********************************************************************
273 * Loads n bytes from p1 and p2, do the diff of the high elements into
274 * d, increments p1 and p2 by i1 and i2
275 * Slightly faster when we know we are loading/diffing 8bytes which
276 * are 8 byte aligned. Reduces need for two loads and two vec_lvsl()'s
277 **********************************************************************/
278 #define PREP_DIFF_8BYTEALIGNED \
280 vec_s16_t pix1v, pix2v; \
281 vec_u8_t pix1v8, pix2v8; \
282 vec_u8_t permPix1, permPix2; \
283 permPix1 = vec_lvsl(0, pix1); \
284 permPix2 = vec_lvsl(0, pix2); \
286 #define VEC_DIFF_H_8BYTE_ALIGNED(p1,i1,p2,i2,n,d) \
287 pix1v8 = vec_perm(vec_ld(0,p1), zero_u8v, permPix1); \
288 pix2v8 = vec_perm(vec_ld(0, p2), zero_u8v, permPix2); \
289 pix1v = vec_u8_to_s16( pix1v8 ); \
290 pix2v = vec_u8_to_s16( pix2v8 ); \
291 d = vec_sub( pix1v, pix2v); \