| OLD | NEW |
| (Empty) | |
| 1 ; Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 ; Use of this source code is governed by a BSD-style license that can be |
| 3 ; found in the LICENSE file. |
| 4 |
| 5 %include "x86inc.asm" |
| 6 |
| 7 ; |
| 8 ; A table used in this file. |
| 9 ; static const int16 kSIMD_ConvertYUVtoARGB_kTable[] = { |
| 10 ; -16, -128, -128, 128, |
| 11 ; 298, 0, 409, 1, |
| 12 ; 298, -100, -208, 1, |
| 13 ; 298, 516, 0, 1, |
| 14 ; }; |
| 15 ; |
| 16 SECTION_RODATA |
| 17 |
| 18 SIMD_ConvertYUVtoARGB_kTable: |
| 19 dw -16, -128, -128, 128 |
| 20 dw 298, 0, 409, 1 |
| 21 dw 298, -100, -208, 1 |
| 22 dw 298, 516, 0, 1, |
| 23 |
| 24 ; |
| 25 ; This file uses SSE, SSE2, SSE3, and SSSE3, which are supported by all ATOM |
| 26 ; processors. |
| 27 ; |
| 28 SECTION_TEXT |
| 29 CPU SSE, SSE2, SSE3, SSSE3 |
| 30 |
| 31 ; |
| 32 ; XMM registers representing constants. We must not use these registers as |
| 33 ; destination operands. |
| 34 ; for (int i = 0; i < 8; i += 4) { |
| 35 ; xmm7.w[i] = -16; xmm7.w[i+1] = -128; xmm7.w[i+2] = -128; xmm7.w[i+3] = 128; |
| 36 ; xmm6.w[i] = 298; xmm6.w[i+1] = 0; xmm6.w[i+2] = 409; xmm6.w[i+3] = 1; |
| 37 ; xmm5.w[i] = 298; xmm5.w[i+1] = -100; xmm5.w[i+2] = -208; xmm5.w[i+3] = 1; |
| 38 ; xmm4.w[i] = 298; xmm4.w[i+1] = 516; xmm4.w[i+2] = 0; xmm4.w[i+3] = 1; |
| 39 ; } |
| 40 ; |
| 41 %define XMM_CONST_BIAS xmm7 |
| 42 %define XMM_CONST_R xmm6 |
| 43 %define XMM_CONST_G xmm5 |
| 44 %define XMM_CONST_B xmm4 |
| 45 |
| 46 ; |
| 47 ; READ_YUV %1 (imm8) |
| 48 ; Read YUV pixels and pack them. This macro stores the result pixels to xmm0 and |
| 49 ; xmm1 as listed below. (This macro sets xmm0.w[3], xmm0.w[7], xmm1.w[3], and |
| 50 ; xmm1.w[7] to 128 so we can add 128.) |
| 51 ; xmm0.w[0] = Y(0) - 16; xmm0.w[1] = U(0) - 128; |
| 52 ; xmm0.w[2] = V(0) - 128; xmm0.w[3] = 128; |
| 53 ; xmm0.w[4] = Y(1) - 16; xmm0.w[5] = U(0) - 128; |
| 54 ; xmm0.w[6] = V(0) - 128; xmm0.w[7] = 128; |
| 55 ; xmm1.w[0] = Y(2) - 16; xmm1.w[1] = U(1) - 128; |
| 56 ; xmm1.w[2] = V(1) - 128; xmm1.w[3] = 128; |
| 57 ; xmm1.w[4] = Y(3) - 16; xmm1.w[5] = U(1) - 128; |
| 58 ; xmm1.w[6] = V(1) - 128; xmm1.w[7] = 128; |
| 59 ; |
| 60 %macro READ_YUV 1 |
| 61 ; Create a zero register so we can used it for unpacking pixels. |
| 62 pxor xmm2, xmm2 |
| 63 |
| 64 ; Read Y pixels. |
| 65 ; xmm0.b[0] = Y(0); xmm0.b[4] = Y(1); xmm0.b[8] = Y(2); xmm0.b[12] = Y(3); |
| 66 %if %1 == 1 |
| 67 movzx TEMPd, BYTE [Yq + WIDTHq * 2] |
| 68 movd xmm0, TEMPd |
| 69 %elif %1 == 2 |
| 70 movzx TEMPd, WORD [Yq + WIDTHq * 2] |
| 71 movd xmm0, TEMPd |
| 72 %elif %1 == 4 |
| 73 movd xmm0, DWORD [Yq + WIDTHq * 2] |
| 74 %else |
| 75 %error unsupported number of pixels. |
| 76 %endif |
| 77 |
| 78 ; Read U pixels. |
| 79 ; xmm0.b[1] = U(0); xmm0.b[5] = U(0); xmm0.b[9] = U(1); xmm0.b[13] = U(1); |
| 80 %if %1 == 1 || %1 == 2 |
| 81 movzx TEMPd, BYTE [Uq + WIDTHq] |
| 82 %elif %1 == 4 |
| 83 movzx TEMPd, WORD [Uq + WIDTHq] |
| 84 %else |
| 85 %error unsupported number of pixels. |
| 86 %endif |
| 87 movd xmm1, TEMPd |
| 88 punpcklbw xmm1, xmm1 |
| 89 punpcklbw xmm0, xmm1 |
| 90 |
| 91 ; Read V pixels. |
| 92 ; xmm0.b[2] = V(0); xmm0.b[6] = V(0); xmm0.b[10] = V(1); xmm0.b[14] = V(1); |
| 93 %if %1 == 1 || %1 == 2 |
| 94 movzx TEMPd, BYTE [Vq + WIDTHq] |
| 95 %elif %1 == 4 |
| 96 movzx TEMPd, WORD [Vq + WIDTHq] |
| 97 %else |
| 98 %error unsupported number of pixels. |
| 99 %endif |
| 100 movd xmm1, TEMPd |
| 101 punpcklbw xmm1, xmm1 |
| 102 punpcklbw xmm1, xmm2 |
| 103 punpcklwd xmm0, xmm1 |
| 104 |
| 105 ; Unpack the input 8-bit pixels to 16-bit words and remove their offsets. |
| 106 %if %1 ==1 || %1 == 2 |
| 107 punpcklbw xmm0, xmm2 |
| 108 |
| 109 paddsw xmm0, XMM_CONST_BIAS |
| 110 %elif %1 == 4 |
| 111 movdqa xmm1, xmm0 |
| 112 punpckhbw xmm1, xmm2 |
| 113 punpcklbw xmm0, xmm2 |
| 114 |
| 115 paddsw xmm0, XMM_CONST_BIAS |
| 116 paddsw xmm1, XMM_CONST_BIAS |
| 117 %else |
| 118 %error unsupported number of pixels. |
| 119 %endif |
| 120 %endmacro |
| 121 |
| 122 ; |
| 123 ; CALC_R %1 (xmm), %2 (xmm), %3 (imm) |
| 124 ; Calculate four red pixels from four packed YUV pixels stored in %2. |
| 125 ; |
| 126 %macro CALC_R 3 |
| 127 pmaddwd %1, XMM_CONST_R |
| 128 %if %3 == 1 || %3 == 2 |
| 129 phaddd %1, %1 |
| 130 %elif %3 == 4 |
| 131 pmaddwd %2, XMM_CONST_R |
| 132 phaddd %1, %2 |
| 133 %else |
| 134 %error unsupported number of pixels. |
| 135 %endif |
| 136 psrad %1, 8 |
| 137 |
| 138 packssdw %1, %1 |
| 139 packuswb %1, %1 |
| 140 %endmacro |
| 141 |
| 142 ; |
| 143 ; CALC_G %1 (xmm), %2 (xmm), %3 (imm) |
| 144 ; Calculate four green pixels from four packed YUV pixels stored in %2. |
| 145 ; |
| 146 %macro CALC_G 3 |
| 147 pmaddwd %1, XMM_CONST_G |
| 148 %if %3 == 1 || %3 == 2 |
| 149 phaddd %1, %1 |
| 150 %elif %3 == 4 |
| 151 pmaddwd %2, XMM_CONST_G |
| 152 phaddd %1, %2 |
| 153 %else |
| 154 %error unsupported number of pixels. |
| 155 %endif |
| 156 psrad %1, 8 |
| 157 |
| 158 packssdw %1, %1 |
| 159 packuswb %1, %1 |
| 160 %endmacro |
| 161 |
| 162 ; |
| 163 ; CALC_B %1 (xmm), %2 (xmm), %3 (imm) |
| 164 ; Calculate four blue pixels from four packed YUV pixels stored in %2. |
| 165 ; |
| 166 %macro CALC_B 3 |
| 167 pmaddwd %1, XMM_CONST_B |
| 168 %if %3 == 1 || %3 == 2 |
| 169 phaddd %1, %1 |
| 170 %elif %3 == 4 |
| 171 pmaddwd %2, XMM_CONST_B |
| 172 phaddd %1, %2 |
| 173 %else |
| 174 %error unsupported number of pixels. |
| 175 %endif |
| 176 psrad %1, 8 |
| 177 |
| 178 packssdw %1, %1 |
| 179 packuswb %1, %1 |
| 180 %endmacro |
| 181 |
| 182 ; |
| 183 ; PACK_ARGB %1 (xmm), %2 (xmm), %3 (xmm) |
| 184 ; Create four ARGB pixels from R pixels stored in %1, G pixels stored in %2, and |
| 185 ; B pixels stored in %3, respecticely. This macro assumes the input pixels are |
| 186 ; stored in the following format. |
| 187 ; %1.b[0] = B(0); %1.b[1] = B(1); %1.b[2] = B(2); %1.b[3] = B(3); |
| 188 ; %2.b[0] = G(0); %2.b[1] = G(1); %2.b[2] = G(2); %2.b[3] = G(3); |
| 189 ; %3.b[0] = R(0); %3.b[1] = R(1); %3.b[2] = R(2); %3.b[3] = R(3); |
| 190 ; This macro writes the output ARGB pixels in the following format: |
| 191 ; %1.b[0] = B(0); %1.b[1] = G(0); %1.b[2] = R(0); %1.b[3] = 0 or 255; |
| 192 ; %1.b[4] = B(1); %1.b[5] = G(1); %1.b[6] = R(1); %1.b[7] = 0 or 255; |
| 193 ; %1.b[8] = B(1); %1.b[9] = G(2); %1.b[10] = R(2); %1.b[11] = 0 or 255; |
| 194 ; %1.b[12] = B(1); %1.b[13] = G(3); %1.b[14] = R(3); %1.b[15] = 0 or 255; |
| 195 ; |
| 196 %macro PACK_ARGB 3 |
| 197 %if ALPHA == 255 |
| 198 pcmpeqd xmm3, xmm3 |
| 199 %elif ALPHA == 0 |
| 200 pxor xmm3, xmm3 |
| 201 %else |
| 202 %error unsupported ALPHA value. |
| 203 %endif |
| 204 punpcklbw %1, %2 |
| 205 punpcklbw %3, xmm3 |
| 206 punpcklwd %1, %3 |
| 207 %endmacro |
| 208 |
| 209 ; |
| 210 ; PACK_RGB %1 (xmm), %2 (imm) |
| 211 ; Packs one ARGB pixel to an RGB pixel. |
| 212 ; for (int i = 0; i < %2; ++i) %1.b[i] = %1.b[i]; |
| 213 ; for (int i = %2; i < 15; ++i) %1.b[i] = %1.b[i + 1]; |
| 214 ; |
| 215 %macro PACK_RGB 2 |
| 216 movdqa xmm1, %1 |
| 217 psrldq xmm1, %2 |
| 218 pslldq xmm1, %2 |
| 219 pxor %1, xmm1 |
| 220 psrldq xmm1, 1 |
| 221 por %1, xmm1 |
| 222 %endmacro |
| 223 |
| 224 ; |
| 225 ; WRITE_ARGB %1 (xmm), %2 (imm) |
| 226 ; Write the specified number of ARGB pixels stored in the source xmm register to |
| 227 ; the output buffer. When the output pixel format is RGB, we convert ARGB pixels |
| 228 ; to RGB pixels and output them. |
| 229 ; |
| 230 %macro WRITE_ARGB 2 |
| 231 |
| 232 %if PIXELSIZE == 4 |
| 233 |
| 234 ; Write ARGB pixels to the destination buffer. |
| 235 %if %2 == 1 |
| 236 movd DWORD [ARGBq + WIDTHq * 4 * 2], %1 |
| 237 %elif %2 == 2 |
| 238 movq QWORD [ARGBq + WIDTHq * 4 * 2], %1 |
| 239 %elif %2 == 4 |
| 240 movdqu DQWORD [ARGBq + WIDTHq * 4 * 2], %1 |
| 241 %else |
| 242 %error unsupported number of pixels. |
| 243 %endif |
| 244 |
| 245 %elif PIXELSIZE == 3 |
| 246 |
| 247 ; Write RGB pixels to the destination buffer. |
| 248 %if %2 == 1 |
| 249 ; Save the WIDTH register to xmm1. This macro breaks the register. |
| 250 MOVq xmm1, WIDTHq |
| 251 |
| 252 ; Write three bytes to the destination buffer. (We do not use maskmovdqu since |
| 253 ; it cause out-of-bound reads. Instead, we copy the source register to TEMPd |
| 254 ; and store it.) |
| 255 lea WIDTHq, [WIDTHq + WIDTHq * 2] |
| 256 movd TEMPd, %1 |
| 257 mov WORD [ARGBq + WIDTHq * 2], TEMPw |
| 258 sar TEMPw, 16 |
| 259 mov BYTE [ARGBq + WIDTHq * 2 + 2], TEMPb |
| 260 |
| 261 ; Restore the WIDTH register. |
| 262 MOVq WIDTHq, xmm1 |
| 263 %elif %2 == 2 |
| 264 ; Pack two ARGB pixels to two RGB pixels. |
| 265 PACK_RGB %1, 4 |
| 266 |
| 267 ; Save the WIDTH register to xmm1. This macro breaks the register. |
| 268 MOVq xmm1, WIDTHq |
| 269 |
| 270 ; Write six bytes to the destination buffer. |
| 271 lea WIDTHq, [WIDTHq + WIDTHq * 2] |
| 272 movd DWORD [ARGBq + WIDTHq * 2], %1 |
| 273 psrldq %1, 4 |
| 274 movd TEMPd, %1 |
| 275 mov WORD [ARGBq + WIDTHq * 2 + 4], TEMPw |
| 276 |
| 277 ; Restore the WIDTH register. |
| 278 MOVq WIDTHq, xmm1 |
| 279 %elif %2 == 4 |
| 280 ; Pack four ARGB pixels to four RGB pixels. |
| 281 PACK_RGB xmm0, 12 |
| 282 PACK_RGB xmm0, 8 |
| 283 PACK_RGB xmm0, 4 |
| 284 |
| 285 ; Write twelve bytes to the destination buffer. |
| 286 mov TEMPq, WIDTHq |
| 287 lea TEMPq, [TEMPq + TEMPq * 2] |
| 288 movq QWORD [ARGBq + TEMPq * 2], %1 |
| 289 psrldq %1, 8 |
| 290 movd DWORD [ARGBq + TEMPq * 2 + 8], %1 |
| 291 %else |
| 292 %error unsupported number of pixels. |
| 293 %endif |
| 294 |
| 295 %else |
| 296 %error unsupported PIXELSIZE value. |
| 297 %endif |
| 298 |
| 299 %endmacro |
| 300 |
| 301 ; |
| 302 ; void media::simd::ConvertYUVtoARGBRow(const uint8* y, |
| 303 ; const uint8* u, |
| 304 ; const uint8* v, |
| 305 ; const uint8* argb, |
| 306 ; int width); |
| 307 ; |
| 308 %ifdef MACHO |
| 309 %define SYMBOL __ZN5media4simd19ConvertYUVtoARGBRowEPKhS2_S2_Phi |
| 310 %elifdef ELF |
| 311 %define SYMBOL _ZN5media4simd19ConvertYUVtoARGBRowEPKhS2_S2_Phi |
| 312 %elifdef MSVC |
| 313 %define SYMBOL ?ConvertYUVtoARGBRow@simd@media@@YAXPBE00PAEH@Z |
| 314 %endif |
| 315 %define PIXELSIZE 4 |
| 316 %define ALPHA 255 |
| 317 |
| 318 %include "convert_yuv_to_rgb_ssse3.inc" |
| 319 |
| 320 ; |
| 321 ; void media::simd::ConvertYUVtoRGBRow(const uint8* y, |
| 322 ; const uint8* u, |
| 323 ; const uint8* v, |
| 324 ; const uint8* rgb, |
| 325 ; int width); |
| 326 ; |
| 327 %ifdef MACHO |
| 328 %define SYMBOL __ZN5media4simd18ConvertYUVtoRGBRowEPKhS2_S2_Phi |
| 329 %elifdef ELF |
| 330 %define SYMBOL _ZN5media4simd18ConvertYUVtoRGBRowEPKhS2_S2_Phi |
| 331 %elifdef MSVC |
| 332 %define SYMBOL ?ConvertYUVtoRGBRow@simd@media@@YAXPBE00PAEH@Z |
| 333 %endif |
| 334 %define PIXELSIZE 3 |
| 335 %define ALPHA 0 |
| 336 %include "convert_yuv_to_rgb_ssse3.inc" |
| OLD | NEW |