x86zigzag.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
  5. * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6. * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  7. * *
  8. * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
  9. * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
  10. * *
  11. ********************************************************************
  12. function:
  13. last mod: $Id: sse2trans.h 15675 2009-02-06 09:43:27Z tterribe $
  14. ********************************************************************/
  15. #if !defined(_x86_x86zigzag_H)
  16. # define _x86_x86zigzag_H (1)
  17. # include "x86enc.h"
  18. /*Converts DCT coefficients from transposed order into zig-zag scan order and
  19. stores them in %[y].
  20. This relies on two macros to load the contents of each row:
  21. OC_ZZ_LOAD_ROW_LO(row,"reg") and OC_ZZ_LOAD_ROW_HI(row,"reg"), which load
  22. the first four and second four entries of each row into the specified
  23. register, respectively.
  24. OC_ZZ_LOAD_ROW_LO must be called before OC_ZZ_LOAD_ROW_HI for the same row
  25. (because when the rows are already in SSE2 registers, loading the high half
  26. destructively modifies the register).
  27. The index of each output element in the original 64-element array should wind
  28. up in the following 8x8 matrix (the letters indicate the order we compute
  29. each 4-tuple below):
  30. A 0 8 1 2 9 16 24 17 B
  31. C 10 3 4 11 18 25 32 40 E
  32. F 33 26 19 12 5 6 13 20 D
  33. G 27 34 41 48 56 49 42 35 I
  34. L 28 21 14 7 15 22 29 36 M
  35. H 43 50 57 58 51 44 37 30 O
  36. N 23 31 38 45 52 59 60 53 J
  37. P 46 39 47 54 61 62 55 63 K
  38. The order of the coefficients within each tuple is reversed in the comments
  39. below to reflect the usual MSB to LSB notation.*/
  40. #define OC_TRANSPOSE_ZIG_ZAG_MMXEXT \
  41. OC_ZZ_LOAD_ROW_LO(0,"%%mm0") /*mm0=03 02 01 00*/ \
  42. OC_ZZ_LOAD_ROW_LO(1,"%%mm1") /*mm1=11 10 09 08*/ \
  43. OC_ZZ_LOAD_ROW_LO(2,"%%mm2") /*mm2=19 18 17 16*/ \
  44. OC_ZZ_LOAD_ROW_LO(3,"%%mm3") /*mm3=27 26 25 24*/ \
  45. OC_ZZ_LOAD_ROW_HI(0,"%%mm4") /*mm4=07 06 05 04*/ \
  46. OC_ZZ_LOAD_ROW_HI(1,"%%mm5") /*mm5=15 14 13 12*/ \
  47. OC_ZZ_LOAD_ROW_HI(2,"%%mm6") /*mm6=23 22 21 20*/ \
  48. "movq %%mm0,%%mm7\n\t" /*mm7=03 02 01 00*/ \
  49. "punpckhdq %%mm1,%%mm0\n\t" /*mm0=11 10 03 02*/ \
  50. "pshufw $0x39,%%mm4,%%mm4\n\t" /*mm4=04 07 06 05*/ \
  51. "punpcklwd %%mm0,%%mm1\n\t" /*mm1=03 09 02 08*/ \
  52. "pshufw $0x39,%%mm5,%%mm5\n\t" /*mm5=12 15 14 13*/ \
  53. "punpcklwd %%mm1,%%mm7\n\t" /*mm7=02 01 08 00 *A*/ \
  54. "movq %%mm7,0x00(%[y])\n\t" \
  55. "punpckhwd %%mm4,%%mm1\n\t" /*mm1=04 03 07 09*/ \
  56. "movq %%mm2,%%mm7\n\t" /*mm7=19 18 17 16*/ \
  57. "punpckhdq %%mm1,%%mm0\n\t" /*mm0=04 03 11 10*/ \
  58. "punpckhwd %%mm5,%%mm7\n\t" /*mm7=12 19 15 18*/ \
  59. "punpcklwd %%mm3,%%mm1\n\t" /*mm1=25 07 24 09*/ \
  60. "punpcklwd %%mm6,%%mm5\n\t" /*mm5=21 14 20 13*/ \
  61. "punpcklwd %%mm2,%%mm1\n\t" /*mm1=17 24 16 09 *B*/ \
  62. OC_ZZ_LOAD_ROW_LO(4,"%%mm2") /*mm2=35 34 33 32*/ \
  63. "movq %%mm1,0x08(%[y])\n\t" \
  64. OC_ZZ_LOAD_ROW_LO(5,"%%mm1") /*mm1=43 42 41 40*/ \
  65. "pshufw $0x78,%%mm0,%%mm0\n\t" /*mm0=11 04 03 10 *C*/ \
  66. "movq %%mm0,0x10(%[y])\n\t" \
  67. "punpckhdq %%mm4,%%mm6\n\t" /*mm6=?? 07 23 22*/ \
  68. "punpckldq %%mm5,%%mm4\n\t" /*mm4=20 13 06 05 *D*/ \
  69. "movq %%mm4,0x28(%[y])\n\t" \
  70. "psrlq $16,%%mm3\n\t" /*mm3=.. 27 26 25*/ \
  71. "pshufw $0x0E,%%mm2,%%mm0\n\t" /*mm0=?? ?? 35 34*/ \
  72. "movq %%mm7,%%mm4\n\t" /*mm4=12 19 15 18*/ \
  73. "punpcklwd %%mm3,%%mm2\n\t" /*mm2=26 33 25 32*/ \
  74. "punpcklwd %%mm1,%%mm4\n\t" /*mm4=41 15 40 18*/ \
  75. "punpckhwd %%mm1,%%mm3\n\t" /*mm3=43 .. 42 27*/ \
  76. "punpckldq %%mm2,%%mm4\n\t" /*mm4=25 32 40 18*/ \
  77. "punpcklwd %%mm0,%%mm3\n\t" /*mm3=35 42 34 27*/ \
  78. OC_ZZ_LOAD_ROW_LO(6,"%%mm0") /*mm0=51 50 49 48*/ \
  79. "pshufw $0x6C,%%mm4,%%mm4\n\t" /*mm4=40 32 25 18 *E*/ \
  80. "movq %%mm4,0x18(%[y])\n\t" \
  81. OC_ZZ_LOAD_ROW_LO(7,"%%mm4") /*mm4=59 58 57 56*/ \
  82. "punpckhdq %%mm7,%%mm2\n\t" /*mm2=12 19 26 33 *F*/ \
  83. "movq %%mm2,0x20(%[y])\n\t" \
  84. "pshufw $0xD0,%%mm1,%%mm1\n\t" /*mm1=43 41 ?? ??*/ \
  85. "pshufw $0x87,%%mm0,%%mm0\n\t" /*mm0=50 48 49 51*/ \
  86. "movq %%mm3,%%mm2\n\t" /*mm2=35 42 34 27*/ \
  87. "punpckhwd %%mm0,%%mm1\n\t" /*mm1=50 43 48 41*/ \
  88. "pshufw $0x93,%%mm4,%%mm4\n\t" /*mm4=58 57 56 59*/ \
  89. "punpckldq %%mm1,%%mm3\n\t" /*mm3=48 41 34 27 *G*/ \
  90. "movq %%mm3,0x30(%[y])\n\t" \
  91. "punpckhdq %%mm4,%%mm1\n\t" /*mm1=58 57 50 43 *H*/ \
  92. "movq %%mm1,0x50(%[y])\n\t" \
  93. OC_ZZ_LOAD_ROW_HI(7,"%%mm1") /*mm1=63 62 61 60*/ \
  94. "punpcklwd %%mm0,%%mm4\n\t" /*mm4=49 56 51 59*/ \
  95. OC_ZZ_LOAD_ROW_HI(6,"%%mm0") /*mm0=55 54 53 52*/ \
  96. "psllq $16,%%mm6\n\t" /*mm6=07 23 22 ..*/ \
  97. "movq %%mm4,%%mm3\n\t" /*mm3=49 56 51 59*/ \
  98. "punpckhdq %%mm2,%%mm4\n\t" /*mm4=35 42 49 56 *I*/ \
  99. OC_ZZ_LOAD_ROW_HI(3,"%%mm2") /*mm2=31 30 29 28*/ \
  100. "movq %%mm4,0x38(%[y])\n\t" \
  101. "punpcklwd %%mm1,%%mm3\n\t" /*mm3=61 51 60 59*/ \
  102. "punpcklwd %%mm6,%%mm7\n\t" /*mm7=22 15 .. ??*/ \
  103. "movq %%mm3,%%mm4\n\t" /*mm4=61 51 60 59*/ \
  104. "punpcklwd %%mm0,%%mm3\n\t" /*mm3=53 60 52 59*/ \
  105. "punpckhwd %%mm0,%%mm4\n\t" /*mm4=55 61 54 51*/ \
  106. OC_ZZ_LOAD_ROW_HI(4,"%%mm0") /*mm0=39 38 37 36*/ \
  107. "pshufw $0xE1,%%mm3,%%mm3\n\t" /*mm3=53 60 59 52 *J*/ \
  108. "movq %%mm3,0x68(%[y])\n\t" \
  109. "movq %%mm4,%%mm3\n\t" /*mm3=?? ?? 54 51*/ \
  110. "pshufw $0x39,%%mm2,%%mm2\n\t" /*mm2=28 31 30 29*/ \
  111. "punpckhwd %%mm1,%%mm4\n\t" /*mm4=63 55 62 61 *K*/ \
  112. OC_ZZ_LOAD_ROW_HI(5,"%%mm1") /*mm1=47 46 45 44*/ \
  113. "movq %%mm4,0x78(%[y])\n\t" \
  114. "punpckhwd %%mm2,%%mm6\n\t" /*mm6=28 07 31 23*/ \
  115. "punpcklwd %%mm0,%%mm2\n\t" /*mm2=37 30 36 29*/ \
  116. "punpckhdq %%mm6,%%mm5\n\t" /*mm5=28 07 21 14*/ \
  117. "pshufw $0x4B,%%mm2,%%mm2\n\t" /*mm2=36 29 30 37*/ \
  118. "pshufw $0x87,%%mm5,%%mm5\n\t" /*mm5=07 14 21 28 *L*/ \
  119. "movq %%mm5,0x40(%[y])\n\t" \
  120. "punpckhdq %%mm2,%%mm7\n\t" /*mm7=36 29 22 15 *M*/ \
  121. "movq %%mm7,0x48(%[y])\n\t" \
  122. "pshufw $0x9C,%%mm1,%%mm1\n\t" /*mm1=46 45 47 44*/ \
  123. "punpckhwd %%mm1,%%mm0\n\t" /*mm0=46 39 45 38*/ \
  124. "punpcklwd %%mm1,%%mm3\n\t" /*mm3=47 54 44 51*/ \
  125. "punpckldq %%mm0,%%mm6\n\t" /*mm6=45 38 31 23 *N*/ \
  126. "movq %%mm6,0x60(%[y])\n\t" \
  127. "punpckhdq %%mm3,%%mm0\n\t" /*mm0=47 54 46 39*/ \
  128. "punpckldq %%mm2,%%mm3\n\t" /*mm3=30 37 44 51 *O*/ \
  129. "movq %%mm3,0x58(%[y])\n\t" \
  130. "pshufw $0xB1,%%mm0,%%mm0\n\t" /*mm0=54 47 39 46 *P*/ \
  131. "movq %%mm0,0x70(%[y])\n\t" \
  132. /*Converts DCT coefficients in %[dct] from natural order into zig-zag scan
  133. order and stores them in %[qdct].
  134. The index of each output element in the original 64-element array should wind
  135. up in the following 8x8 matrix (the letters indicate the order we compute
  136. each 4-tuple below):
  137. A 0 1 8 16 9 2 3 10 B
  138. C 17 24 32 25 18 11 4 5 D
  139. E 12 19 26 33 40 48 41 34 I
  140. H 27 20 13 6 7 14 21 28 G
  141. K 35 42 49 56 57 50 43 36 J
  142. F 29 22 15 23 30 37 44 51 M
  143. P 58 59 52 45 38 31 39 46 L
  144. N 53 60 61 54 47 55 62 63 O
  145. The order of the coefficients within each tuple is reversed in the comments
  146. below to reflect the usual MSB to LSB notation.*/
  147. #define OC_ZIG_ZAG_MMXEXT \
  148. "movq 0x00(%[dct]),%%mm0\n\t" /*mm0=03 02 01 00*/ \
  149. "movq 0x08(%[dct]),%%mm1\n\t" /*mm1=07 06 05 04*/ \
  150. "movq 0x10(%[dct]),%%mm2\n\t" /*mm2=11 10 09 08*/ \
  151. "movq 0x20(%[dct]),%%mm3\n\t" /*mm3=19 18 17 16*/ \
  152. "movq 0x30(%[dct]),%%mm4\n\t" /*mm4=27 26 25 24*/ \
  153. "movq 0x40(%[dct]),%%mm5\n\t" /*mm5=35 34 33 32*/ \
  154. "movq %%mm2,%%mm7\n\t" /*mm7=11 10 09 08*/ \
  155. "punpcklwd %%mm3,%%mm2\n\t" /*mm2=17 09 16 08*/ \
  156. "movq %%mm0,%%mm6\n\t" /*mm6=03 02 01 00*/ \
  157. "punpckldq %%mm2,%%mm0\n\t" /*mm0=16 08 01 00 *A*/ \
  158. "movq %%mm0,0x00(%[qdct])\n\t" \
  159. "movq 0x18(%[dct]),%%mm0\n\t" /*mm0=15 14 13 12*/ \
  160. "punpckhdq %%mm6,%%mm6\n\t" /*mm6=03 02 03 02*/ \
  161. "psrlq $16,%%mm7\n\t" /*mm7=.. 11 10 09*/ \
  162. "punpckldq %%mm7,%%mm6\n\t" /*mm6=10 09 03 02*/ \
  163. "punpckhwd %%mm7,%%mm3\n\t" /*mm3=.. 19 11 18*/ \
  164. "pshufw $0xD2,%%mm6,%%mm6\n\t" /*mm6=10 03 02 09 *B*/ \
  165. "movq %%mm6,0x08(%[qdct])\n\t" \
  166. "psrlq $48,%%mm2\n\t" /*mm2=.. .. .. 17*/ \
  167. "movq %%mm1,%%mm6\n\t" /*mm6=07 06 05 04*/ \
  168. "punpcklwd %%mm5,%%mm2\n\t" /*mm2=33 .. 32 17*/ \
  169. "movq %%mm3,%%mm7\n\t" /*mm7=.. 19 11 18*/ \
  170. "punpckldq %%mm1,%%mm3\n\t" /*mm3=05 04 11 18 *C*/ \
  171. "por %%mm2,%%mm7\n\t" /*mm7=33 19 ?? ??*/ \
  172. "punpcklwd %%mm4,%%mm2\n\t" /*mm2=25 32 24 17 *D**/ \
  173. "movq %%mm2,0x10(%[qdct])\n\t" \
  174. "movq %%mm3,0x18(%[qdct])\n\t" \
  175. "movq 0x28(%[dct]),%%mm2\n\t" /*mm2=23 22 21 20*/ \
  176. "movq 0x38(%[dct]),%%mm1\n\t" /*mm1=31 30 29 28*/ \
  177. "pshufw $0x9C,%%mm0,%%mm3\n\t" /*mm3=14 13 15 12*/ \
  178. "punpckhdq %%mm7,%%mm7\n\t" /*mm7=33 19 33 19*/ \
  179. "punpckhwd %%mm3,%%mm6\n\t" /*mm6=14 07 13 06*/ \
  180. "punpckldq %%mm0,%%mm0\n\t" /*mm0=13 12 13 12*/ \
  181. "punpcklwd %%mm1,%%mm3\n\t" /*mm3=29 15 28 12*/ \
  182. "punpckhwd %%mm4,%%mm0\n\t" /*mm0=27 13 26 12*/ \
  183. "pshufw $0xB4,%%mm3,%%mm3\n\t" /*mm3=15 29 28 12*/ \
  184. "psrlq $48,%%mm4\n\t" /*mm4=.. .. .. 27*/ \
  185. "punpcklwd %%mm7,%%mm0\n\t" /*mm0=33 26 19 12 *E*/ \
  186. "punpcklwd %%mm1,%%mm4\n\t" /*mm4=29 .. 28 27*/ \
  187. "punpckhwd %%mm2,%%mm3\n\t" /*mm3=23 15 22 29 *F*/ \
  188. "movq %%mm0,0x20(%[qdct])\n\t" \
  189. "movq %%mm3,0x50(%[qdct])\n\t" \
  190. "movq 0x60(%[dct]),%%mm3\n\t" /*mm3=51 50 49 48*/ \
  191. "movq 0x70(%[dct]),%%mm7\n\t" /*mm7=59 58 57 56*/ \
  192. "movq 0x50(%[dct]),%%mm0\n\t" /*mm0=43 42 41 40*/ \
  193. "punpcklwd %%mm4,%%mm2\n\t" /*mm2=28 21 27 20*/ \
  194. "psrlq $32,%%mm5\n\t" /*mm5=.. .. 35 34*/ \
  195. "movq %%mm2,%%mm4\n\t" /*mm4=28 21 27 20*/ \
  196. "punpckldq %%mm6,%%mm2\n\t" /*mm2=13 06 27 20*/ \
  197. "punpckhdq %%mm4,%%mm6\n\t" /*mm6=28 21 14 07 *G*/ \
  198. "movq %%mm3,%%mm4\n\t" /*mm4=51 50 49 48*/ \
  199. "pshufw $0xB1,%%mm2,%%mm2\n\t" /*mm2=06 13 20 27 *H*/ \
  200. "movq %%mm2,0x30(%[qdct])\n\t" \
  201. "movq %%mm6,0x38(%[qdct])\n\t" \
  202. "movq 0x48(%[dct]),%%mm2\n\t" /*mm2=39 38 37 36*/ \
  203. "punpcklwd %%mm5,%%mm4\n\t" /*mm4=35 49 34 48*/ \
  204. "movq 0x58(%[dct]),%%mm5\n\t" /*mm5=47 46 45 44*/ \
  205. "punpckldq %%mm7,%%mm6\n\t" /*mm6=57 56 14 07*/ \
  206. "psrlq $32,%%mm3\n\t" /*mm3=.. .. 51 50*/ \
  207. "punpckhwd %%mm0,%%mm6\n\t" /*mm6=43 57 42 56*/ \
  208. "punpcklwd %%mm4,%%mm0\n\t" /*mm0=34 41 48 40 *I*/ \
  209. "pshufw $0x4E,%%mm6,%%mm6\n\t" /*mm6=42 56 43 57*/ \
  210. "movq %%mm0,0x28(%[qdct])\n\t" \
  211. "punpcklwd %%mm2,%%mm3\n\t" /*mm3=37 51 36 50*/ \
  212. "punpckhwd %%mm6,%%mm4\n\t" /*mm4=42 35 56 49*/ \
  213. "punpcklwd %%mm3,%%mm6\n\t" /*mm6=36 43 50 57 *J*/ \
  214. "pshufw $0x4E,%%mm4,%%mm4\n\t" /*mm4=56 49 42 35 *K*/ \
  215. "movq %%mm4,0x40(%[qdct])\n\t" \
  216. "movq %%mm6,0x48(%[qdct])\n\t" \
  217. "movq 0x68(%[dct]),%%mm6\n\t" /*mm6=55 54 53 52*/ \
  218. "movq 0x78(%[dct]),%%mm0\n\t" /*mm0=63 62 61 60*/ \
  219. "psrlq $32,%%mm1\n\t" /*mm1=.. .. 31 30*/ \
  220. "pshufw $0xD8,%%mm5,%%mm5\n\t" /*mm5=47 45 46 44*/ \
  221. "pshufw $0x0B,%%mm3,%%mm3\n\t" /*mm3=50 50 51 37*/ \
  222. "punpcklwd %%mm5,%%mm1\n\t" /*mm1=46 31 44 30*/ \
  223. "pshufw $0xC9,%%mm6,%%mm6\n\t" /*mm6=55 52 54 53*/ \
  224. "punpckhwd %%mm1,%%mm2\n\t" /*mm2=46 39 31 38 *L*/ \
  225. "punpcklwd %%mm3,%%mm1\n\t" /*mm1=51 44 37 30 *M*/ \
  226. "movq %%mm2,0x68(%[qdct])\n\t" \
  227. "movq %%mm1,0x58(%[qdct])\n\t" \
  228. "punpckhwd %%mm6,%%mm5\n\t" /*mm5=55 47 52 45*/ \
  229. "punpckldq %%mm0,%%mm6\n\t" /*mm6=61 60 54 53*/ \
  230. "pshufw $0x10,%%mm5,%%mm4\n\t" /*mm4=45 52 45 45*/ \
  231. "pshufw $0x78,%%mm6,%%mm6\n\t" /*mm6=53 60 61 54 *N*/ \
  232. "punpckhdq %%mm0,%%mm5\n\t" /*mm5=63 62 55 47 *O*/ \
  233. "punpckhdq %%mm4,%%mm7\n\t" /*mm7=45 52 59 58 *P*/ \
  234. "movq %%mm6,0x70(%[qdct])\n\t" \
  235. "movq %%mm5,0x78(%[qdct])\n\t" \
  236. "movq %%mm7,0x60(%[qdct])\n\t" \
  237. #endif