mmx.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. #include <linux/config.h>
  2. #include <linux/types.h>
  3. #include <linux/string.h>
  4. #include <linux/sched.h>
  5. #include <asm/i387.h>
  6. #include <asm/hardirq.h> 
  7. /*
  8.  * MMX 3DNow! library helper functions
  9.  *
  10.  * To do:
  11.  * We can use MMX just for prefetch in IRQ's. This may be a win. 
  12.  * (reported so on K6-III)
  13.  * We should use a better code neutral filler for the short jump
  14.  * leal ebx. [ebx] is apparently best for K6-2, but Cyrix ??
  15.  * We also want to clobber the filler register so we dont get any
  16.  * register forwarding stalls on the filler. 
  17.  *
  18.  * Add *user handling. Checksums are not a win with MMX on any CPU
  19.  * tested so far for any MMX solution figured.
  20.  *
  21.  * 22/09/2000 - Arjan van de Ven 
  22.  * Improved for non-egineering-sample Athlons 
  23.  *
  24.  */
  25.  
  26. void *_mmx_memcpy(void *to, const void *from, size_t len)
  27. {
  28. void *p;
  29. int i;
  30. if (in_interrupt())
  31. return __memcpy(to, from, len);
  32. p = to;
  33. i = len >> 6; /* len/64 */
  34. kernel_fpu_begin();
  35. __asm__ __volatile__ (
  36. "1: prefetch (%0)n" /* This set is 28 bytes */
  37. "   prefetch 64(%0)n"
  38. "   prefetch 128(%0)n"
  39. "   prefetch 192(%0)n"
  40. "   prefetch 256(%0)n"
  41. "2:  n"
  42. ".section .fixup, "ax"n"
  43. "3: movw $0x1AEB, 1bn" /* jmp on 26 bytes */
  44. "   jmp 2bn"
  45. ".previousn"
  46. ".section __ex_table,"a"n"
  47. " .align 4n"
  48. " .long 1b, 3bn"
  49. ".previous"
  50. : : "r" (from) );
  51. for(; i>0; i--)
  52. {
  53. __asm__ __volatile__ (
  54. "1:  prefetch 320(%0)n"
  55. "2:  movq (%0), %%mm0n"
  56. "  movq 8(%0), %%mm1n"
  57. "  movq 16(%0), %%mm2n"
  58. "  movq 24(%0), %%mm3n"
  59. "  movq %%mm0, (%1)n"
  60. "  movq %%mm1, 8(%1)n"
  61. "  movq %%mm2, 16(%1)n"
  62. "  movq %%mm3, 24(%1)n"
  63. "  movq 32(%0), %%mm0n"
  64. "  movq 40(%0), %%mm1n"
  65. "  movq 48(%0), %%mm2n"
  66. "  movq 56(%0), %%mm3n"
  67. "  movq %%mm0, 32(%1)n"
  68. "  movq %%mm1, 40(%1)n"
  69. "  movq %%mm2, 48(%1)n"
  70. "  movq %%mm3, 56(%1)n"
  71. ".section .fixup, "ax"n"
  72. "3: movw $0x05EB, 1bn" /* jmp on 5 bytes */
  73. "   jmp 2bn"
  74. ".previousn"
  75. ".section __ex_table,"a"n"
  76. " .align 4n"
  77. " .long 1b, 3bn"
  78. ".previous"
  79. : : "r" (from), "r" (to) : "memory");
  80. from+=64;
  81. to+=64;
  82. }
  83. /*
  84.  * Now do the tail of the block
  85.  */
  86. __memcpy(to, from, len&63);
  87. kernel_fpu_end();
  88. return p;
  89. }
  90. #ifdef CONFIG_MK7
  91. /*
  92.  * The K7 has streaming cache bypass load/store. The Cyrix III, K6 and
  93.  * other MMX using processors do not.
  94.  */
  95. static void fast_clear_page(void *page)
  96. {
  97. int i;
  98. kernel_fpu_begin();
  99. __asm__ __volatile__ (
  100. "  pxor %%mm0, %%mm0n" : :
  101. );
  102. for(i=0;i<4096/64;i++)
  103. {
  104. __asm__ __volatile__ (
  105. "  movntq %%mm0, (%0)n"
  106. "  movntq %%mm0, 8(%0)n"
  107. "  movntq %%mm0, 16(%0)n"
  108. "  movntq %%mm0, 24(%0)n"
  109. "  movntq %%mm0, 32(%0)n"
  110. "  movntq %%mm0, 40(%0)n"
  111. "  movntq %%mm0, 48(%0)n"
  112. "  movntq %%mm0, 56(%0)n"
  113. : : "r" (page) : "memory");
  114. page+=64;
  115. }
  116. /* since movntq is weakly-ordered, a "sfence" is needed to become
  117.  * ordered again.
  118.  */
  119. __asm__ __volatile__ (
  120. "  sfence n" : :
  121. );
  122. kernel_fpu_end();
  123. }
  124. static void fast_copy_page(void *to, void *from)
  125. {
  126. int i;
  127. kernel_fpu_begin();
  128. /* maybe the prefetch stuff can go before the expensive fnsave...
  129.  * but that is for later. -AV
  130.  */
  131. __asm__ __volatile__ (
  132. "1: prefetch (%0)n"
  133. "   prefetch 64(%0)n"
  134. "   prefetch 128(%0)n"
  135. "   prefetch 192(%0)n"
  136. "   prefetch 256(%0)n"
  137. "2:  n"
  138. ".section .fixup, "ax"n"
  139. "3: movw $0x1AEB, 1bn" /* jmp on 26 bytes */
  140. "   jmp 2bn"
  141. ".previousn"
  142. ".section __ex_table,"a"n"
  143. " .align 4n"
  144. " .long 1b, 3bn"
  145. ".previous"
  146. : : "r" (from) );
  147. for(i=0; i<(4096-320)/64; i++)
  148. {
  149. __asm__ __volatile__ (
  150. "1: prefetch 320(%0)n"
  151. "2: movq (%0), %%mm0n"
  152. "   movntq %%mm0, (%1)n"
  153. "   movq 8(%0), %%mm1n"
  154. "   movntq %%mm1, 8(%1)n"
  155. "   movq 16(%0), %%mm2n"
  156. "   movntq %%mm2, 16(%1)n"
  157. "   movq 24(%0), %%mm3n"
  158. "   movntq %%mm3, 24(%1)n"
  159. "   movq 32(%0), %%mm4n"
  160. "   movntq %%mm4, 32(%1)n"
  161. "   movq 40(%0), %%mm5n"
  162. "   movntq %%mm5, 40(%1)n"
  163. "   movq 48(%0), %%mm6n"
  164. "   movntq %%mm6, 48(%1)n"
  165. "   movq 56(%0), %%mm7n"
  166. "   movntq %%mm7, 56(%1)n"
  167. ".section .fixup, "ax"n"
  168. "3: movw $0x05EB, 1bn" /* jmp on 5 bytes */
  169. "   jmp 2bn"
  170. ".previousn"
  171. ".section __ex_table,"a"n"
  172. " .align 4n"
  173. " .long 1b, 3bn"
  174. ".previous"
  175. : : "r" (from), "r" (to) : "memory");
  176. from+=64;
  177. to+=64;
  178. }
  179. for(i=(4096-320)/64; i<4096/64; i++)
  180. {
  181. __asm__ __volatile__ (
  182. "2: movq (%0), %%mm0n"
  183. "   movntq %%mm0, (%1)n"
  184. "   movq 8(%0), %%mm1n"
  185. "   movntq %%mm1, 8(%1)n"
  186. "   movq 16(%0), %%mm2n"
  187. "   movntq %%mm2, 16(%1)n"
  188. "   movq 24(%0), %%mm3n"
  189. "   movntq %%mm3, 24(%1)n"
  190. "   movq 32(%0), %%mm4n"
  191. "   movntq %%mm4, 32(%1)n"
  192. "   movq 40(%0), %%mm5n"
  193. "   movntq %%mm5, 40(%1)n"
  194. "   movq 48(%0), %%mm6n"
  195. "   movntq %%mm6, 48(%1)n"
  196. "   movq 56(%0), %%mm7n"
  197. "   movntq %%mm7, 56(%1)n"
  198. : : "r" (from), "r" (to) : "memory");
  199. from+=64;
  200. to+=64;
  201. }
  202. /* since movntq is weakly-ordered, a "sfence" is needed to become
  203.  * ordered again.
  204.  */
  205. __asm__ __volatile__ (
  206. "  sfence n" : :
  207. );
  208. kernel_fpu_end();
  209. }
  210. #else
  211. /*
  212.  * Generic MMX implementation without K7 specific streaming
  213.  */
  214.  
  215. static void fast_clear_page(void *page)
  216. {
  217. int i;
  218. kernel_fpu_begin();
  219. __asm__ __volatile__ (
  220. "  pxor %%mm0, %%mm0n" : :
  221. );
  222. for(i=0;i<4096/128;i++)
  223. {
  224. __asm__ __volatile__ (
  225. "  movq %%mm0, (%0)n"
  226. "  movq %%mm0, 8(%0)n"
  227. "  movq %%mm0, 16(%0)n"
  228. "  movq %%mm0, 24(%0)n"
  229. "  movq %%mm0, 32(%0)n"
  230. "  movq %%mm0, 40(%0)n"
  231. "  movq %%mm0, 48(%0)n"
  232. "  movq %%mm0, 56(%0)n"
  233. "  movq %%mm0, 64(%0)n"
  234. "  movq %%mm0, 72(%0)n"
  235. "  movq %%mm0, 80(%0)n"
  236. "  movq %%mm0, 88(%0)n"
  237. "  movq %%mm0, 96(%0)n"
  238. "  movq %%mm0, 104(%0)n"
  239. "  movq %%mm0, 112(%0)n"
  240. "  movq %%mm0, 120(%0)n"
  241. : : "r" (page) : "memory");
  242. page+=128;
  243. }
  244. kernel_fpu_end();
  245. }
  246. static void fast_copy_page(void *to, void *from)
  247. {
  248. int i;
  249. kernel_fpu_begin();
  250. __asm__ __volatile__ (
  251. "1: prefetch (%0)n"
  252. "   prefetch 64(%0)n"
  253. "   prefetch 128(%0)n"
  254. "   prefetch 192(%0)n"
  255. "   prefetch 256(%0)n"
  256. "2:  n"
  257. ".section .fixup, "ax"n"
  258. "3: movw $0x1AEB, 1bn" /* jmp on 26 bytes */
  259. "   jmp 2bn"
  260. ".previousn"
  261. ".section __ex_table,"a"n"
  262. " .align 4n"
  263. " .long 1b, 3bn"
  264. ".previous"
  265. : : "r" (from) );
  266. for(i=0; i<4096/64; i++)
  267. {
  268. __asm__ __volatile__ (
  269. "1: prefetch 320(%0)n"
  270. "2: movq (%0), %%mm0n"
  271. "   movq 8(%0), %%mm1n"
  272. "   movq 16(%0), %%mm2n"
  273. "   movq 24(%0), %%mm3n"
  274. "   movq %%mm0, (%1)n"
  275. "   movq %%mm1, 8(%1)n"
  276. "   movq %%mm2, 16(%1)n"
  277. "   movq %%mm3, 24(%1)n"
  278. "   movq 32(%0), %%mm0n"
  279. "   movq 40(%0), %%mm1n"
  280. "   movq 48(%0), %%mm2n"
  281. "   movq 56(%0), %%mm3n"
  282. "   movq %%mm0, 32(%1)n"
  283. "   movq %%mm1, 40(%1)n"
  284. "   movq %%mm2, 48(%1)n"
  285. "   movq %%mm3, 56(%1)n"
  286. ".section .fixup, "ax"n"
  287. "3: movw $0x05EB, 1bn" /* jmp on 5 bytes */
  288. "   jmp 2bn"
  289. ".previousn"
  290. ".section __ex_table,"a"n"
  291. " .align 4n"
  292. " .long 1b, 3bn"
  293. ".previous"
  294. : : "r" (from), "r" (to) : "memory");
  295. from+=64;
  296. to+=64;
  297. }
  298. kernel_fpu_end();
  299. }
  300. #endif
  301. /*
  302.  * Favour MMX for page clear and copy. 
  303.  */
  304. static void slow_zero_page(void * page)
  305. {
  306. int d0, d1;
  307. __asm__ __volatile__( 
  308. "cldnt" 
  309. "rep ; stosl" 
  310. : "=&c" (d0), "=&D" (d1)
  311. :"a" (0),"1" (page),"0" (1024)
  312. :"memory");
  313. }
  314.  
  315. void mmx_clear_page(void * page)
  316. {
  317. if(in_interrupt())
  318. slow_zero_page(page);
  319. else
  320. fast_clear_page(page);
  321. }
  322. static void slow_copy_page(void *to, void *from)
  323. {
  324. int d0, d1, d2;
  325. __asm__ __volatile__( 
  326. "cldnt" 
  327. "rep ; movsl" 
  328. : "=&c" (d0), "=&D" (d1), "=&S" (d2) 
  329. : "0" (1024),"1" ((long) to),"2" ((long) from) 
  330. : "memory");
  331. }
  332.   
  333. void mmx_copy_page(void *to, void *from)
  334. {
  335. if(in_interrupt())
  336. slow_copy_page(to, from);
  337. else
  338. fast_copy_page(to, from);
  339. }