fdct_bfin.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. * fdct BlackFin
  3. *
  4. * Copyright (C) 2007 Marc Hoffman <marc.hoffman@analog.com>
  5. *
  6. * This file is part of Libav.
  7. *
  8. * Libav is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * Libav is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with Libav; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. /*
  23. void ff_bfin_fdct (DCTELEM *buf);
  24. This implementation works only for 8x8 input. The range of input
  25. must be -256 to 255 i.e. 8bit input represented in a 16bit data
  26. word. The original data must be sign extended into the 16bit data
  27. words.
  28. Chen factorization of
  29. 8
  30. X(m) = sum (x(n) * cos ((2n+1)*m*pi/16))
  31. n=0
  32. C4
  33. 0 --*-------------*0+7---*-----*0+3-------*-*-------------------> 0
  34. \ / \ / X S4,S4
  35. 1 --*-\---------/-*1+6---*-\-/-*1+2-------*-*-------------------> 4
  36. \ / \ -C4 C3
  37. 2 --*---\-----/---*2+5---*-/-\-*1-2---------------*-*-----------> 2
  38. \ / / \ X S3,-S3
  39. 3 --*-----\-/-----*3+4---*-----*0-3---------------*-*-----------> 6
  40. / C7 C3
  41. 4 --*-----/-\-----*3-4------------*-*4+5--*-----*---------------> 1
  42. / \ -C4 X \ /S7 C3
  43. 5 --*---/-----\---*2-5---*-*------*=*4-5----\-/------*-*--------> 5
  44. / \ X S4,S4 / X S3,-S3
  45. 6 --*-/---------\-*1-6---*-*------*=*7-6----/-\------*-*--------> 3
  46. / \ C4 X / \-S7 C3
  47. --*-------------*0-7------------*-*7+6--*-----*---------------> 7
  48. C7
  49. Notation
  50. Cn = cos(n*pi/8) used throughout the code.
  51. Registers used:
  52. R0, R1, R2, R3, R4, R5, R6,R7, P0, P1, P2, P3, P4, P5, A0, A1.
  53. Other registers used:
  54. I0, I1, I2, I3, B0, B2, B3, M0, M1, L3 registers and LC0.
  55. Input - r0 - pointer to start of DCTELEM *block
  56. Output - The DCT output coefficients in the DCTELEM *block
  57. Register constraint:
  58. This code is called from jpeg_encode.
  59. R6, R5, R4 if modified should be stored and restored.
  60. Performance: (Timer version 0.6.33)
  61. Code Size : 240 Bytes.
  62. Memory Required :
  63. Input Matrix : 8 * 8 * 2 Bytes.
  64. Coefficients : 16 Bytes
  65. Temporary matrix: 8 * 8 * 2 Bytes.
  66. Cycle Count :26+{18+8*(14+2S)}*2 where S -> Stalls
  67. (7.45 c/pel)
  68. -----------------------------------------
  69. | Size | Forward DCT | Inverse DCT |
  70. -----------------------------------------
  71. | 8x8 | 284 Cycles | 311 Cycles |
  72. -----------------------------------------
  73. Ck = int16(cos(k/16*pi)*32767+.5)/2
  74. #define C4 23170
  75. #define C3 13623
  76. #define C6 6270
  77. #define C7 3196
  78. Sk = int16(sin(k/16*pi)*32767+.5)/2
  79. #define S4 11585
  80. #define S3 9102
  81. #define S6 15137
  82. #define S7 16069
  83. the coefficients are ordered as follows:
  84. short dct_coef[]
  85. C4,S4,
  86. C6,S6,
  87. C7,S7,
  88. S3,C3,
  89. -----------------------------------------------------------
  90. Libav conformance testing results
  91. -----------------------------------------------------------
  92. dct-test: modified with the following
  93. dct_error("BFINfdct", 0, ff_bfin_fdct, fdct, test);
  94. produces the following output:
  95. libavcodec> ./dct-test
  96. Libav DCT/IDCT test
  97. 2 -131 -6 -48 -36 33 -83 24
  98. 34 52 -24 -15 5 92 57 143
  99. -67 -43 -1 74 -16 5 -71 32
  100. -78 106 92 -34 -38 81 20 -18
  101. 7 -62 40 2 -15 90 -62 -83
  102. -83 1 -104 -13 43 -19 7 11
  103. -63 31 12 -29 83 72 21 10
  104. -17 -63 -15 73 50 -91 159 -14
  105. DCT BFINfdct: err_inf=2 err2=0.16425938 syserr=0.00795000 maxout=2098 blockSumErr=27
  106. DCT BFINfdct: 92.1 kdct/s
  107. */
  108. #include "config.h"
  109. #include "config_bfin.h"
  110. #if defined(__FDPIC__) && CONFIG_SRAM
  111. .section .l1.data.B,"aw",@progbits
  112. #else
  113. .data
  114. #endif
  115. .align 4;
  116. dct_coeff:
  117. .short 0x5a82, 0x2d41, 0x187e, 0x3b21, 0x0c7c, 0x3ec5, 0x238e, 0x3537;
  118. #if defined(__FDPIC__) && CONFIG_SRAM
  119. .section .l1.data.A,"aw",@progbits
  120. #endif
  121. .align 4
  122. vtmp: .space 128
  123. .text
  124. DEFUN(fdct,mL1,
  125. (DCTELEM *block)):
  126. [--SP] = (R7:4, P5:3); // Push the registers onto the stack.
  127. b0 = r0;
  128. RELOC(r0, P3, dct_coeff);
  129. b3 = r0;
  130. RELOC(r0, P3, vtmp);
  131. b2 = r0;
  132. L3 = 16; // L3 is set to 16 to make the coefficient
  133. // array Circular.
  134. //----------------------------------------------------------------------------
  135. /*
  136. * I0, I1, and I2 registers are used to read the input data. I3 register is used
  137. * to read the coefficients. P0 and P1 registers are used for writing the output
  138. * data.
  139. */
  140. M0 = 12 (X); // All these initializations are used in the
  141. M1 = 16 (X); // modification of address offsets.
  142. M2 = 128 (X);
  143. P2 = 16;
  144. P3 = 32 (X);
  145. P4 = -110 (X);
  146. P5 = -62 (X);
  147. P0 = 2(X);
  148. // Prescale the input to get the correct precision.
  149. i0=b0;
  150. i1=b0;
  151. lsetup (.0, .1) LC0 = P3;
  152. r0=[i0++];
  153. .0: r1=r0<<3 (v) || r0=[i0++] ;
  154. .1: [i1++]=r1;
  155. /*
  156. * B0 points to the "in" buffer.
  157. * B2 points to "temp" buffer in the first iteration.
  158. */
  159. lsetup (.2, .3) LC0 = P0;
  160. .2:
  161. I0 = B0; // I0 points to Input Element (0, 0).
  162. I1 = B0; // Element 1 and 0 is read in R0.
  163. I1 += M0 || R0 = [I0++]; // I1 points to Input Element (0, 6).
  164. I2 = I1; // Element 6 is read into R3.H.
  165. I2 -= 4 || R3.H = W[I1++]; // I2 points to Input Element (0, 4).
  166. I3 = B3; // I3 points to Coefficients.
  167. P0 = B2; // P0 points to temporary array Element
  168. // (0, 0).
  169. P1 = B2; // P1 points to temporary array.
  170. R7 = [P1++P2] || R2 = [I2++]; // P1 points to temporary array
  171. // Element (1, 0).
  172. // R7 is a dummy read. X4,X5
  173. // are read into R2.
  174. R3.L = W[I1--]; // X7 is read into R3.L.
  175. R1.H = W[I0++]; // X2 is read into R1.H.
  176. /*
  177. * X0 = (X0 + X7) / 2.
  178. * X1 = (X1 + X6) / 2.
  179. * X6 = (X1 - X6) / 2.
  180. * X7 = (X0 - X7) / 2.
  181. * It reads the data 3 in R1.L.
  182. */
  183. R0 = R0 +|+ R3, R3 = R0 -|- R3 || R1.L = W[I0++] || NOP;
  184. /*
  185. * X2 = (X2 + X5) / 2.
  186. * X3 = (X3 + X4) / 2.
  187. * X4 = (X3 - X4) / 2.
  188. * X5 = (X2 - X5) / 2.
  189. * R7 = C4 = cos(4*pi/16)
  190. */
  191. R1 = R1 +|+ R2, R2 = R1 -|- R2 (CO) || NOP || R7 = [I3++];
  192. /*
  193. * At the end of stage 1 R0 has (1,0), R1 has (2,3), R2 has (4, 5) and
  194. * R3 has (6,7).
  195. * Where the notation (x, y) represents uper/lower half pairs.
  196. */
  197. /*
  198. * X0 = X0 + X3.
  199. * X1 = X1 + X2.
  200. * X2 = X1 - X2.
  201. * X3 = X0 - X3.
  202. */
  203. R0 = R0 +|+ R1, R1 = R0 -|- R1;
  204. lsetup (.row0, .row1) LC1 = P2 >> 1; // 1d dct, loops 8x
  205. .row0:
  206. /*
  207. * This is part 2 computation continued.....
  208. * A1 = X6 * cos(pi/4)
  209. * A0 = X6 * cos(pi/4)
  210. * A1 = A1 - X5 * cos(pi/4)
  211. * A0 = A0 + X5 * cos(pi/4).
  212. * The instruction W[I0] = R3.L is used for packing it to R2.L.
  213. */
  214. A1=R3.H*R7.l, A0=R3.H*R7.l || I1+=M1 || W[I0] = R3.L;
  215. R4.H=(A1-=R2.L*R7.l), R4.L=(A0+=R2.L*R7.l) || I2+=M0 || NOP;
  216. /* R0 = (X1,X0) R1 = (X2,X3) R4 = (X5, X6). */
  217. /*
  218. * A1 = X0 * cos(pi/4)
  219. * A0 = X0 * cos(pi/4)
  220. * A1 = A1 - X1 * cos(pi/4)
  221. * A0 = A0 + X1 * cos(pi/4)
  222. * R7 = (C2,C6)
  223. */
  224. A1=R0.L*R7.h, A0=R0.L*R7.h || NOP || R3.H=W[I1++];
  225. R5.H=(A1-=R0.H*R7.h),R5.L=(A0+=R0.H*R7.h) || R7=[I3++] || NOP;
  226. /*
  227. * A1 = X2 * cos(3pi/8)
  228. * A0 = X3 * cos(3pi/8)
  229. * A1 = A1 + X3 * cos(pi/8)
  230. * A0 = A0 - X2 * cos(pi/8)
  231. * R3 = cos(pi/4)
  232. * R7 = (cos(7pi/8),cos(pi/8))
  233. * X4 = X4 + X5.
  234. * X5 = X4 - X5.
  235. * X6 = X7 - X6.
  236. * X7 = X7 + X6.
  237. */
  238. A1=R1.H*R7.L, A0=R1.L*R7.L || W[P0++P3]=R5.L || R2.L=W[I0];
  239. R2=R2+|+R4, R4=R2-|-R4 || I0+=4 || R3.L=W[I1--];
  240. R6.H=(A1+=R1.L*R7.H),R6.L=(A0 -= R1.H * R7.H) || I0+=4 || R7=[I3++];
  241. /* R2 = (X4, X7) R4 = (X5,X6) R5 = (X1, X0) R6 = (X2,X3). */
  242. /*
  243. * A1 = X4 * cos(7pi/16)
  244. * A0 = X7 * cos(7pi/16)
  245. * A1 = A1 + X7 * cos(pi/16)
  246. * A0 = A0 - X4 * cos(pi/16)
  247. */
  248. A1=R2.H*R7.L, A0=R2.L*R7.L || W[P0++P3]=R6.H || R0=[I0++];
  249. R2.H=(A1+=R2.L*R7.H),R2.L=(A0-=R2.H*R7.H) || W[P0++P3]=R5.H || R7=[I3++];
  250. /*
  251. * A1 = X5 * cos(3pi/16)
  252. * A0 = X6 * cos(3pi/16)
  253. * A1 = A1 + X6 * cos(5pi/16)
  254. * A0 = A0 - X5 * cos(5pi/16)
  255. * The output values are written.
  256. */
  257. A1=R4.H*R7.H, A0=R4.L*R7.H || W[P0++P2]=R6.L || R1.H=W[I0++];
  258. R4.H=(A1+=R4.L*R7.L),R4.L=(A0-=R4.H*R7.L) || W[P0++P4]=R2.L || R1.L=W[I0++];
  259. /* Beginning of next stage, **pipelined** + drain and store the
  260. rest of the column store. */
  261. R0=R0+|+R3,R3=R0-|-R3 || W[P1++P3]=R2.H || R2=[I2++];
  262. R1=R1+|+R2,R2=R1-|-R2 (CO) || W[P1++P3]=R4.L || R7=[I3++];
  263. .row1: R0=R0+|+R1,R1=R0-|-R1 || W[P1++P5]=R4.H || NOP;
  264. // Exchange input with output.
  265. B1 = B0;
  266. B0 = B2;
  267. .3: B2 = B1;
  268. L3=0;
  269. (r7:4,p5:3) = [sp++];
  270. RTS;
  271. DEFUN_END(fdct)