mmxidct.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  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$
  14. ********************************************************************/
  15. /*MMX acceleration of Theora's iDCT.
  16. Originally written by Rudolf Marek, based on code from On2's VP3.*/
  17. #include "x86int.h"
  18. #include "../dct.h"
  19. #if defined(OC_X86_ASM)
  20. /*These are offsets into the table of constants below.*/
  21. /*7 rows of cosines, in order: pi/16 * (1 ... 7).*/
  22. #define OC_COSINE_OFFSET (8)
  23. /*A row of 8's.*/
  24. #define OC_EIGHT_OFFSET (0)
  25. /*A table of constants used by the MMX routines.*/
  26. static const OC_ALIGN16(ogg_uint16_t) OC_IDCT_CONSTS[(1+7)*4]={
  27. 8, 8, 8, 8,
  28. (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
  29. (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
  30. (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
  31. (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
  32. (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5,
  33. (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5,
  34. (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4,
  35. (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4,
  36. (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3,
  37. (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3,
  38. (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
  39. (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
  40. (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
  41. (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1
  42. };
  43. /*38 cycles*/
  44. #define OC_IDCT_BEGIN(_y,_x) __asm{ \
  45. __asm movq mm2,OC_I(3,_x) \
  46. __asm movq mm6,OC_C(3) \
  47. __asm movq mm4,mm2 \
  48. __asm movq mm7,OC_J(5,_x) \
  49. __asm pmulhw mm4,mm6 \
  50. __asm movq mm1,OC_C(5) \
  51. __asm pmulhw mm6,mm7 \
  52. __asm movq mm5,mm1 \
  53. __asm pmulhw mm1,mm2 \
  54. __asm movq mm3,OC_I(1,_x) \
  55. __asm pmulhw mm5,mm7 \
  56. __asm movq mm0,OC_C(1) \
  57. __asm paddw mm4,mm2 \
  58. __asm paddw mm6,mm7 \
  59. __asm paddw mm2,mm1 \
  60. __asm movq mm1,OC_J(7,_x) \
  61. __asm paddw mm7,mm5 \
  62. __asm movq mm5,mm0 \
  63. __asm pmulhw mm0,mm3 \
  64. __asm paddw mm4,mm7 \
  65. __asm pmulhw mm5,mm1 \
  66. __asm movq mm7,OC_C(7) \
  67. __asm psubw mm6,mm2 \
  68. __asm paddw mm0,mm3 \
  69. __asm pmulhw mm3,mm7 \
  70. __asm movq mm2,OC_I(2,_x) \
  71. __asm pmulhw mm7,mm1 \
  72. __asm paddw mm5,mm1 \
  73. __asm movq mm1,mm2 \
  74. __asm pmulhw mm2,OC_C(2) \
  75. __asm psubw mm3,mm5 \
  76. __asm movq mm5,OC_J(6,_x) \
  77. __asm paddw mm0,mm7 \
  78. __asm movq mm7,mm5 \
  79. __asm psubw mm0,mm4 \
  80. __asm pmulhw mm5,OC_C(2) \
  81. __asm paddw mm2,mm1 \
  82. __asm pmulhw mm1,OC_C(6) \
  83. __asm paddw mm4,mm4 \
  84. __asm paddw mm4,mm0 \
  85. __asm psubw mm3,mm6 \
  86. __asm paddw mm5,mm7 \
  87. __asm paddw mm6,mm6 \
  88. __asm pmulhw mm7,OC_C(6) \
  89. __asm paddw mm6,mm3 \
  90. __asm movq OC_I(1,_y),mm4 \
  91. __asm psubw mm1,mm5 \
  92. __asm movq mm4,OC_C(4) \
  93. __asm movq mm5,mm3 \
  94. __asm pmulhw mm3,mm4 \
  95. __asm paddw mm7,mm2 \
  96. __asm movq OC_I(2,_y),mm6 \
  97. __asm movq mm2,mm0 \
  98. __asm movq mm6,OC_I(0,_x) \
  99. __asm pmulhw mm0,mm4 \
  100. __asm paddw mm5,mm3 \
  101. __asm movq mm3,OC_J(4,_x) \
  102. __asm psubw mm5,mm1 \
  103. __asm paddw mm2,mm0 \
  104. __asm psubw mm6,mm3 \
  105. __asm movq mm0,mm6 \
  106. __asm pmulhw mm6,mm4 \
  107. __asm paddw mm3,mm3 \
  108. __asm paddw mm1,mm1 \
  109. __asm paddw mm3,mm0 \
  110. __asm paddw mm1,mm5 \
  111. __asm pmulhw mm4,mm3 \
  112. __asm paddw mm6,mm0 \
  113. __asm psubw mm6,mm2 \
  114. __asm paddw mm2,mm2 \
  115. __asm movq mm0,OC_I(1,_y) \
  116. __asm paddw mm2,mm6 \
  117. __asm paddw mm4,mm3 \
  118. __asm psubw mm2,mm1 \
  119. }
  120. /*38+8=46 cycles.*/
  121. #define OC_ROW_IDCT(_y,_x) __asm{ \
  122. OC_IDCT_BEGIN(_y,_x) \
  123. /*r3=D'*/ \
  124. __asm movq mm3,OC_I(2,_y) \
  125. /*r4=E'=E-G*/ \
  126. __asm psubw mm4,mm7 \
  127. /*r1=H'+H'*/ \
  128. __asm paddw mm1,mm1 \
  129. /*r7=G+G*/ \
  130. __asm paddw mm7,mm7 \
  131. /*r1=R1=A''+H'*/ \
  132. __asm paddw mm1,mm2 \
  133. /*r7=G'=E+G*/ \
  134. __asm paddw mm7,mm4 \
  135. /*r4=R4=E'-D'*/ \
  136. __asm psubw mm4,mm3 \
  137. __asm paddw mm3,mm3 \
  138. /*r6=R6=F'-B''*/ \
  139. __asm psubw mm6,mm5 \
  140. __asm paddw mm5,mm5 \
  141. /*r3=R3=E'+D'*/ \
  142. __asm paddw mm3,mm4 \
  143. /*r5=R5=F'+B''*/ \
  144. __asm paddw mm5,mm6 \
  145. /*r7=R7=G'-C'*/ \
  146. __asm psubw mm7,mm0 \
  147. __asm paddw mm0,mm0 \
  148. /*Save R1.*/ \
  149. __asm movq OC_I(1,_y),mm1 \
  150. /*r0=R0=G.+C.*/ \
  151. __asm paddw mm0,mm7 \
  152. }
  153. /*The following macro does two 4x4 transposes in place.
  154. At entry, we assume:
  155. r0 = a3 a2 a1 a0
  156. I(1) = b3 b2 b1 b0
  157. r2 = c3 c2 c1 c0
  158. r3 = d3 d2 d1 d0
  159. r4 = e3 e2 e1 e0
  160. r5 = f3 f2 f1 f0
  161. r6 = g3 g2 g1 g0
  162. r7 = h3 h2 h1 h0
  163. At exit, we have:
  164. I(0) = d0 c0 b0 a0
  165. I(1) = d1 c1 b1 a1
  166. I(2) = d2 c2 b2 a2
  167. I(3) = d3 c3 b3 a3
  168. J(4) = h0 g0 f0 e0
  169. J(5) = h1 g1 f1 e1
  170. J(6) = h2 g2 f2 e2
  171. J(7) = h3 g3 f3 e3
  172. I(0) I(1) I(2) I(3) is the transpose of r0 I(1) r2 r3.
  173. J(4) J(5) J(6) J(7) is the transpose of r4 r5 r6 r7.
  174. Since r1 is free at entry, we calculate the Js first.*/
  175. /*19 cycles.*/
  176. #define OC_TRANSPOSE(_y) __asm{ \
  177. __asm movq mm1,mm4 \
  178. __asm punpcklwd mm4,mm5 \
  179. __asm movq OC_I(0,_y),mm0 \
  180. __asm punpckhwd mm1,mm5 \
  181. __asm movq mm0,mm6 \
  182. __asm punpcklwd mm6,mm7 \
  183. __asm movq mm5,mm4 \
  184. __asm punpckldq mm4,mm6 \
  185. __asm punpckhdq mm5,mm6 \
  186. __asm movq mm6,mm1 \
  187. __asm movq OC_J(4,_y),mm4 \
  188. __asm punpckhwd mm0,mm7 \
  189. __asm movq OC_J(5,_y),mm5 \
  190. __asm punpckhdq mm6,mm0 \
  191. __asm movq mm4,OC_I(0,_y) \
  192. __asm punpckldq mm1,mm0 \
  193. __asm movq mm5,OC_I(1,_y) \
  194. __asm movq mm0,mm4 \
  195. __asm movq OC_J(7,_y),mm6 \
  196. __asm punpcklwd mm0,mm5 \
  197. __asm movq OC_J(6,_y),mm1 \
  198. __asm punpckhwd mm4,mm5 \
  199. __asm movq mm5,mm2 \
  200. __asm punpcklwd mm2,mm3 \
  201. __asm movq mm1,mm0 \
  202. __asm punpckldq mm0,mm2 \
  203. __asm punpckhdq mm1,mm2 \
  204. __asm movq mm2,mm4 \
  205. __asm movq OC_I(0,_y),mm0 \
  206. __asm punpckhwd mm5,mm3 \
  207. __asm movq OC_I(1,_y),mm1 \
  208. __asm punpckhdq mm4,mm5 \
  209. __asm punpckldq mm2,mm5 \
  210. __asm movq OC_I(3,_y),mm4 \
  211. __asm movq OC_I(2,_y),mm2 \
  212. }
  213. /*38+19=57 cycles.*/
  214. #define OC_COLUMN_IDCT(_y) __asm{ \
  215. OC_IDCT_BEGIN(_y,_y) \
  216. __asm paddw mm2,OC_8 \
  217. /*r1=H'+H'*/ \
  218. __asm paddw mm1,mm1 \
  219. /*r1=R1=A''+H'*/ \
  220. __asm paddw mm1,mm2 \
  221. /*r2=NR2*/ \
  222. __asm psraw mm2,4 \
  223. /*r4=E'=E-G*/ \
  224. __asm psubw mm4,mm7 \
  225. /*r1=NR1*/ \
  226. __asm psraw mm1,4 \
  227. /*r3=D'*/ \
  228. __asm movq mm3,OC_I(2,_y) \
  229. /*r7=G+G*/ \
  230. __asm paddw mm7,mm7 \
  231. /*Store NR2 at I(2).*/ \
  232. __asm movq OC_I(2,_y),mm2 \
  233. /*r7=G'=E+G*/ \
  234. __asm paddw mm7,mm4 \
  235. /*Store NR1 at I(1).*/ \
  236. __asm movq OC_I(1,_y),mm1 \
  237. /*r4=R4=E'-D'*/ \
  238. __asm psubw mm4,mm3 \
  239. __asm paddw mm4,OC_8 \
  240. /*r3=D'+D'*/ \
  241. __asm paddw mm3,mm3 \
  242. /*r3=R3=E'+D'*/ \
  243. __asm paddw mm3,mm4 \
  244. /*r4=NR4*/ \
  245. __asm psraw mm4,4 \
  246. /*r6=R6=F'-B''*/ \
  247. __asm psubw mm6,mm5 \
  248. /*r3=NR3*/ \
  249. __asm psraw mm3,4 \
  250. __asm paddw mm6,OC_8 \
  251. /*r5=B''+B''*/ \
  252. __asm paddw mm5,mm5 \
  253. /*r5=R5=F'+B''*/ \
  254. __asm paddw mm5,mm6 \
  255. /*r6=NR6*/ \
  256. __asm psraw mm6,4 \
  257. /*Store NR4 at J(4).*/ \
  258. __asm movq OC_J(4,_y),mm4 \
  259. /*r5=NR5*/ \
  260. __asm psraw mm5,4 \
  261. /*Store NR3 at I(3).*/ \
  262. __asm movq OC_I(3,_y),mm3 \
  263. /*r7=R7=G'-C'*/ \
  264. __asm psubw mm7,mm0 \
  265. __asm paddw mm7,OC_8 \
  266. /*r0=C'+C'*/ \
  267. __asm paddw mm0,mm0 \
  268. /*r0=R0=G'+C'*/ \
  269. __asm paddw mm0,mm7 \
  270. /*r7=NR7*/ \
  271. __asm psraw mm7,4 \
  272. /*Store NR6 at J(6).*/ \
  273. __asm movq OC_J(6,_y),mm6 \
  274. /*r0=NR0*/ \
  275. __asm psraw mm0,4 \
  276. /*Store NR5 at J(5).*/ \
  277. __asm movq OC_J(5,_y),mm5 \
  278. /*Store NR7 at J(7).*/ \
  279. __asm movq OC_J(7,_y),mm7 \
  280. /*Store NR0 at I(0).*/ \
  281. __asm movq OC_I(0,_y),mm0 \
  282. }
  283. #define OC_MID(_m,_i) [CONSTS+_m+(_i)*8]
  284. #define OC_C(_i) OC_MID(OC_COSINE_OFFSET,_i-1)
  285. #define OC_8 OC_MID(OC_EIGHT_OFFSET,0)
  286. static void oc_idct8x8_slow(ogg_int16_t _y[64],ogg_int16_t _x[64]){
  287. int i;
  288. /*This routine accepts an 8x8 matrix, but in partially transposed form.
  289. Every 4x4 block is transposed.*/
  290. __asm{
  291. #define CONSTS eax
  292. #define Y edx
  293. #define X ecx
  294. mov CONSTS,offset OC_IDCT_CONSTS
  295. mov Y,_y
  296. mov X,_x
  297. #define OC_I(_k,_y) [(_y)+(_k)*16]
  298. #define OC_J(_k,_y) [(_y)+((_k)-4)*16+8]
  299. OC_ROW_IDCT(Y,X)
  300. OC_TRANSPOSE(Y)
  301. #undef OC_I
  302. #undef OC_J
  303. #define OC_I(_k,_y) [(_y)+(_k)*16+64]
  304. #define OC_J(_k,_y) [(_y)+((_k)-4)*16+72]
  305. OC_ROW_IDCT(Y,X)
  306. OC_TRANSPOSE(Y)
  307. #undef OC_I
  308. #undef OC_J
  309. #define OC_I(_k,_y) [(_y)+(_k)*16]
  310. #define OC_J(_k,_y) OC_I(_k,_y)
  311. OC_COLUMN_IDCT(Y)
  312. #undef OC_I
  313. #undef OC_J
  314. #define OC_I(_k,_y) [(_y)+(_k)*16+8]
  315. #define OC_J(_k,_y) OC_I(_k,_y)
  316. OC_COLUMN_IDCT(Y)
  317. #undef OC_I
  318. #undef OC_J
  319. #undef CONSTS
  320. #undef Y
  321. #undef X
  322. }
  323. __asm pxor mm0,mm0;
  324. for(i=0;i<4;i++){
  325. ogg_int16_t *x;
  326. x=_x+16*i;
  327. #define X ecx
  328. __asm{
  329. mov X,x
  330. movq [X+0x00],mm0
  331. movq [X+0x08],mm0
  332. movq [X+0x10],mm0
  333. movq [X+0x18],mm0
  334. }
  335. #undef X
  336. }
  337. }
  338. /*25 cycles.*/
  339. #define OC_IDCT_BEGIN_10(_y,_x) __asm{ \
  340. __asm movq mm2,OC_I(3,_x) \
  341. __asm nop \
  342. __asm movq mm6,OC_C(3) \
  343. __asm movq mm4,mm2 \
  344. __asm movq mm1,OC_C(5) \
  345. __asm pmulhw mm4,mm6 \
  346. __asm movq mm3,OC_I(1,_x) \
  347. __asm pmulhw mm1,mm2 \
  348. __asm movq mm0,OC_C(1) \
  349. __asm paddw mm4,mm2 \
  350. __asm pxor mm6,mm6 \
  351. __asm paddw mm2,mm1 \
  352. __asm movq mm5,OC_I(2,_x) \
  353. __asm pmulhw mm0,mm3 \
  354. __asm movq mm1,mm5 \
  355. __asm paddw mm0,mm3 \
  356. __asm pmulhw mm3,OC_C(7) \
  357. __asm psubw mm6,mm2 \
  358. __asm pmulhw mm5,OC_C(2) \
  359. __asm psubw mm0,mm4 \
  360. __asm movq mm7,OC_I(2,_x) \
  361. __asm paddw mm4,mm4 \
  362. __asm paddw mm7,mm5 \
  363. __asm paddw mm4,mm0 \
  364. __asm pmulhw mm1,OC_C(6) \
  365. __asm psubw mm3,mm6 \
  366. __asm movq OC_I(1,_y),mm4 \
  367. __asm paddw mm6,mm6 \
  368. __asm movq mm4,OC_C(4) \
  369. __asm paddw mm6,mm3 \
  370. __asm movq mm5,mm3 \
  371. __asm pmulhw mm3,mm4 \
  372. __asm movq OC_I(2,_y),mm6 \
  373. __asm movq mm2,mm0 \
  374. __asm movq mm6,OC_I(0,_x) \
  375. __asm pmulhw mm0,mm4 \
  376. __asm paddw mm5,mm3 \
  377. __asm paddw mm2,mm0 \
  378. __asm psubw mm5,mm1 \
  379. __asm pmulhw mm6,mm4 \
  380. __asm paddw mm6,OC_I(0,_x) \
  381. __asm paddw mm1,mm1 \
  382. __asm movq mm4,mm6 \
  383. __asm paddw mm1,mm5 \
  384. __asm psubw mm6,mm2 \
  385. __asm paddw mm2,mm2 \
  386. __asm movq mm0,OC_I(1,_y) \
  387. __asm paddw mm2,mm6 \
  388. __asm psubw mm2,mm1 \
  389. __asm nop \
  390. }
  391. /*25+8=33 cycles.*/
  392. #define OC_ROW_IDCT_10(_y,_x) __asm{ \
  393. OC_IDCT_BEGIN_10(_y,_x) \
  394. /*r3=D'*/ \
  395. __asm movq mm3,OC_I(2,_y) \
  396. /*r4=E'=E-G*/ \
  397. __asm psubw mm4,mm7 \
  398. /*r1=H'+H'*/ \
  399. __asm paddw mm1,mm1 \
  400. /*r7=G+G*/ \
  401. __asm paddw mm7,mm7 \
  402. /*r1=R1=A''+H'*/ \
  403. __asm paddw mm1,mm2 \
  404. /*r7=G'=E+G*/ \
  405. __asm paddw mm7,mm4 \
  406. /*r4=R4=E'-D'*/ \
  407. __asm psubw mm4,mm3 \
  408. __asm paddw mm3,mm3 \
  409. /*r6=R6=F'-B''*/ \
  410. __asm psubw mm6,mm5 \
  411. __asm paddw mm5,mm5 \
  412. /*r3=R3=E'+D'*/ \
  413. __asm paddw mm3,mm4 \
  414. /*r5=R5=F'+B''*/ \
  415. __asm paddw mm5,mm6 \
  416. /*r7=R7=G'-C'*/ \
  417. __asm psubw mm7,mm0 \
  418. __asm paddw mm0,mm0 \
  419. /*Save R1.*/ \
  420. __asm movq OC_I(1,_y),mm1 \
  421. /*r0=R0=G'+C'*/ \
  422. __asm paddw mm0,mm7 \
  423. }
  424. /*25+19=44 cycles'*/
  425. #define OC_COLUMN_IDCT_10(_y) __asm{ \
  426. OC_IDCT_BEGIN_10(_y,_y) \
  427. __asm paddw mm2,OC_8 \
  428. /*r1=H'+H'*/ \
  429. __asm paddw mm1,mm1 \
  430. /*r1=R1=A''+H'*/ \
  431. __asm paddw mm1,mm2 \
  432. /*r2=NR2*/ \
  433. __asm psraw mm2,4 \
  434. /*r4=E'=E-G*/ \
  435. __asm psubw mm4,mm7 \
  436. /*r1=NR1*/ \
  437. __asm psraw mm1,4 \
  438. /*r3=D'*/ \
  439. __asm movq mm3,OC_I(2,_y) \
  440. /*r7=G+G*/ \
  441. __asm paddw mm7,mm7 \
  442. /*Store NR2 at I(2).*/ \
  443. __asm movq OC_I(2,_y),mm2 \
  444. /*r7=G'=E+G*/ \
  445. __asm paddw mm7,mm4 \
  446. /*Store NR1 at I(1).*/ \
  447. __asm movq OC_I(1,_y),mm1 \
  448. /*r4=R4=E'-D'*/ \
  449. __asm psubw mm4,mm3 \
  450. __asm paddw mm4,OC_8 \
  451. /*r3=D'+D'*/ \
  452. __asm paddw mm3,mm3 \
  453. /*r3=R3=E'+D'*/ \
  454. __asm paddw mm3,mm4 \
  455. /*r4=NR4*/ \
  456. __asm psraw mm4,4 \
  457. /*r6=R6=F'-B''*/ \
  458. __asm psubw mm6,mm5 \
  459. /*r3=NR3*/ \
  460. __asm psraw mm3,4 \
  461. __asm paddw mm6,OC_8 \
  462. /*r5=B''+B''*/ \
  463. __asm paddw mm5,mm5 \
  464. /*r5=R5=F'+B''*/ \
  465. __asm paddw mm5,mm6 \
  466. /*r6=NR6*/ \
  467. __asm psraw mm6,4 \
  468. /*Store NR4 at J(4).*/ \
  469. __asm movq OC_J(4,_y),mm4 \
  470. /*r5=NR5*/ \
  471. __asm psraw mm5,4 \
  472. /*Store NR3 at I(3).*/ \
  473. __asm movq OC_I(3,_y),mm3 \
  474. /*r7=R7=G'-C'*/ \
  475. __asm psubw mm7,mm0 \
  476. __asm paddw mm7,OC_8 \
  477. /*r0=C'+C'*/ \
  478. __asm paddw mm0,mm0 \
  479. /*r0=R0=G'+C'*/ \
  480. __asm paddw mm0,mm7 \
  481. /*r7=NR7*/ \
  482. __asm psraw mm7,4 \
  483. /*Store NR6 at J(6).*/ \
  484. __asm movq OC_J(6,_y),mm6 \
  485. /*r0=NR0*/ \
  486. __asm psraw mm0,4 \
  487. /*Store NR5 at J(5).*/ \
  488. __asm movq OC_J(5,_y),mm5 \
  489. /*Store NR7 at J(7).*/ \
  490. __asm movq OC_J(7,_y),mm7 \
  491. /*Store NR0 at I(0).*/ \
  492. __asm movq OC_I(0,_y),mm0 \
  493. }
  494. static void oc_idct8x8_10(ogg_int16_t _y[64],ogg_int16_t _x[64]){
  495. __asm{
  496. #define CONSTS eax
  497. #define Y edx
  498. #define X ecx
  499. mov CONSTS,offset OC_IDCT_CONSTS
  500. mov Y,_y
  501. mov X,_x
  502. #define OC_I(_k,_y) [(_y)+(_k)*16]
  503. #define OC_J(_k,_y) [(_y)+((_k)-4)*16+8]
  504. /*Done with dequant, descramble, and partial transpose.
  505. Now do the iDCT itself.*/
  506. OC_ROW_IDCT_10(Y,X)
  507. OC_TRANSPOSE(Y)
  508. #undef OC_I
  509. #undef OC_J
  510. #define OC_I(_k,_y) [(_y)+(_k)*16]
  511. #define OC_J(_k,_y) OC_I(_k,_y)
  512. OC_COLUMN_IDCT_10(Y)
  513. #undef OC_I
  514. #undef OC_J
  515. #define OC_I(_k,_y) [(_y)+(_k)*16+8]
  516. #define OC_J(_k,_y) OC_I(_k,_y)
  517. OC_COLUMN_IDCT_10(Y)
  518. #undef OC_I
  519. #undef OC_J
  520. #undef CONSTS
  521. #undef Y
  522. #undef X
  523. }
  524. #define X ecx
  525. __asm{
  526. pxor mm0,mm0;
  527. mov X,_x
  528. movq [X+0x00],mm0
  529. movq [X+0x10],mm0
  530. movq [X+0x20],mm0
  531. movq [X+0x30],mm0
  532. }
  533. #undef X
  534. }
  535. /*Performs an inverse 8x8 Type-II DCT transform.
  536. The input is assumed to be scaled by a factor of 4 relative to orthonormal
  537. version of the transform.*/
  538. void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
  539. /*_last_zzi is subtly different from an actual count of the number of
  540. coefficients we decoded for this block.
  541. It contains the value of zzi BEFORE the final token in the block was
  542. decoded.
  543. In most cases this is an EOB token (the continuation of an EOB run from a
  544. previous block counts), and so this is the same as the coefficient count.
  545. However, in the case that the last token was NOT an EOB token, but filled
  546. the block up with exactly 64 coefficients, _last_zzi will be less than 64.
  547. Provided the last token was not a pure zero run, the minimum value it can
  548. be is 46, and so that doesn't affect any of the cases in this routine.
  549. However, if the last token WAS a pure zero run of length 63, then _last_zzi
  550. will be 1 while the number of coefficients decoded is 64.
  551. Thus, we will trigger the following special case, where the real
  552. coefficient count would not.
  553. Note also that a zero run of length 64 will give _last_zzi a value of 0,
  554. but we still process the DC coefficient, which might have a non-zero value
  555. due to DC prediction.
  556. Although convoluted, this is arguably the correct behavior: it allows us to
  557. use a smaller transform when the block ends with a long zero run instead
  558. of a normal EOB token.
  559. It could be smarter... multiple separate zero runs at the end of a block
  560. will fool it, but an encoder that generates these really deserves what it
  561. gets.
  562. Needless to say we inherited this approach from VP3.*/
  563. /*Perform the iDCT.*/
  564. if(_last_zzi<=10)oc_idct8x8_10(_y,_x);
  565. else oc_idct8x8_slow(_y,_x);
  566. }
  567. #endif